Browse Source

The video decoding thread efficiently waits for a video to be created before doing anything, rather than sleeping for 2ms in a loop. Reduces the CPU usage of the video worker thread to ~0% when no videos are loaded.

Alex Szpakowski 9 years ago
parent
commit
a0bbcce8ee

+ 0 - 7
src/modules/thread/Channel.cpp

@@ -77,8 +77,6 @@ Channel::Channel()
 	, sent(0)
 	, received(0)
 {
-	mutex = newMutex();
-	cond = newConditional();
 }
 
 Channel::Channel(const std::string &name)
@@ -87,15 +85,10 @@ Channel::Channel(const std::string &name)
 	, sent(0)
 	, received(0)
 {
-	mutex = newMutex();
-	cond = newConditional();
 }
 
 Channel::~Channel()
 {
-	delete mutex;
-	delete cond;
-
 	if (named)
 	{
 		Lock l(namedChannelMutex);

+ 2 - 2
src/modules/thread/Channel.h

@@ -60,8 +60,8 @@ private:
 	void lockMutex();
 	void unlockMutex();
 
-	Mutex *mutex;
-	Conditional *cond;
+	MutexRef mutex;
+	ConditionalRef cond;
 	std::queue<Variant> queue;
 	bool named;
 	std::string name;

+ 26 - 1
src/modules/thread/threads.cpp

@@ -43,7 +43,7 @@ Lock::~Lock()
 }
 
 EmptyLock::EmptyLock()
-	: mutex(0)
+	: mutex(nullptr)
 {
 }
 
@@ -119,5 +119,30 @@ MutexRef::operator Mutex*() const
 	return mutex;
 }
 
+Mutex *MutexRef::operator->() const
+{
+	return mutex;
+}
+
+ConditionalRef::ConditionalRef()
+	: conditional(newConditional())
+{
+}
+
+ConditionalRef::~ConditionalRef()
+{
+	delete conditional;
+}
+
+ConditionalRef::operator Conditional*() const
+{
+	return conditional;
+}
+
+Conditional *ConditionalRef::operator->() const
+{
+	return conditional;
+}
+
 } // thread
 } // love

+ 14 - 0
src/modules/thread/threads.h

@@ -103,11 +103,25 @@ public:
 	~MutexRef();
 
 	operator Mutex*() const;
+	Mutex *operator->() const;
 
 private:
 	Mutex *mutex;
 };
 
+class ConditionalRef
+{
+public:
+	ConditionalRef();
+	~ConditionalRef();
+
+	operator Conditional*() const;
+	Conditional *operator->() const;
+
+private:
+	Conditional *conditional;
+};
+
 Mutex *newMutex();
 Conditional *newConditional();
 Thread *newThread(Threadable *t);

+ 1 - 6
src/modules/timer/Timer.cpp

@@ -114,7 +114,7 @@ double Timer::getTimerPeriod()
 	return 0;
 }
 
-double Timer::getTimeSinceEpoch()
+double Timer::getTime()
 {
 	// The timer period (reciprocal of the frequency.)
 	static const double timerPeriod = getTimerPeriod();
@@ -145,10 +145,5 @@ double Timer::getTimeSinceEpoch()
 #endif
 }
 
-double Timer::getTime() const
-{
-	return getTimeSinceEpoch();
-}
-
 } // timer
 } // love

+ 1 - 2
src/modules/timer/Timer.h

@@ -76,8 +76,7 @@ public:
 	 * and increases monotonically.
 	 * @return The time (in seconds)
 	 **/
-	virtual double getTime() const;
-	static double getTimeSinceEpoch();
+	static double getTime();
 
 private:
 

+ 26 - 19
src/modules/video/theora/Video.cpp

@@ -71,6 +71,7 @@ void Worker::addStream(VideoStream *stream)
 {
 	love::thread::Lock l(mutex);
 	streams.push_back(stream);
+	cond->broadcast();
 }
 
 void Worker::stop()
@@ -78,6 +79,7 @@ void Worker::stop()
 	{
 		love::thread::Lock l(mutex);
 		stopping = true;
+		cond->broadcast();
 	}
 
 	owner->wait();
@@ -85,34 +87,39 @@ void Worker::stop()
 
 void Worker::threadFunction()
 {
-	double lastFrame = love::timer::Timer::getTimeSinceEpoch();
+	double lastFrame = love::timer::Timer::getTime();
+
 	while (true)
 	{
-		double curFrame = love::timer::Timer::getTimeSinceEpoch();
-		double dt = curFrame-lastFrame;
-		lastFrame = curFrame;
+		love::sleep(2);
 
+		love::thread::Lock l(mutex);
+
+		while (!stopping && streams.empty())
 		{
-			love::thread::Lock l(mutex);
+			cond->wait(mutex);
+			lastFrame = love::timer::Timer::getTime();
+		}
 
-			if (stopping)
-				return;
+		if (stopping)
+			return;
 
-			for (auto it = streams.begin(); it != streams.end(); ++it)
+		double curFrame = love::timer::Timer::getTime();
+		double dt = curFrame-lastFrame;
+		lastFrame = curFrame;
+
+		for (auto it = streams.begin(); it != streams.end(); ++it)
+		{
+			VideoStream *stream = *it;
+			if (stream->getReferenceCount() == 1)
 			{
-				VideoStream *stream = *it;
-				if (stream->getReferenceCount() == 1)
-				{
-					// We're the only ones left
-					streams.erase(it);
-					break;
-				}
-
-				stream->threadedFillBackBuffer(dt);
+				// We're the only ones left
+				streams.erase(it);
+				break;
 			}
-		}
 
-		love::sleep(2);
+			stream->threadedFillBackBuffer(dt);
+		}
 	}
 }
 

+ 4 - 1
src/modules/video/theora/Video.h

@@ -68,10 +68,13 @@ public:
 	void stop();
 
 private:
+
 	std::vector<StrongRef<VideoStream>> streams;
+
 	love::thread::MutexRef mutex;
+	love::thread::ConditionalRef cond;
 
-	volatile bool stopping;
+	bool stopping;
 }; // Worker
 
 } // theora