From: est31 <MTest31@outlook.com>
Date: Mon, 29 Jun 2015 09:06:03 +0000 (+0200)
Subject: Add UpdateThread and use it for minimap and mesh threads
X-Git-Tag: 0.4.13~164
X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=29dda9f356042c403b3b7da1d717d32b45c9b6de;p=oweals%2Fminetest.git

Add UpdateThread and use it for minimap and mesh threads
---

diff --git a/src/client.cpp b/src/client.cpp
index ce48df953..b02e6229c 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -139,7 +139,7 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se
 
 // Returned pointer must be deleted
 // Returns NULL if queue is empty
-QueuedMeshUpdate * MeshUpdateQueue::pop()
+QueuedMeshUpdate *MeshUpdateQueue::pop()
 {
 	JMutexAutoLock lock(m_mutex);
 
@@ -162,26 +162,17 @@ QueuedMeshUpdate * MeshUpdateQueue::pop()
 	MeshUpdateThread
 */
 
-void * MeshUpdateThread::Thread()
+void MeshUpdateThread::enqueueUpdate(v3s16 p, MeshMakeData *data,
+		bool ack_block_to_server, bool urgent)
 {
-	ThreadStarted();
-
-	log_register_thread("MeshUpdateThread");
-
-	DSTACK(__FUNCTION_NAME);
-
-	BEGIN_DEBUG_EXCEPTION_HANDLER
-
-	porting::setThreadName("MeshUpdateThread");
+	m_queue_in.addBlock(p, data, ack_block_to_server, urgent);
+	deferUpdate();
+}
 
-	while(!StopRequested())
-	{
-		QueuedMeshUpdate *q = m_queue_in.pop();
-		if(q == NULL)
-		{
-			sleep_ms(3);
-			continue;
-		}
+void MeshUpdateThread::doUpdate()
+{
+	QueuedMeshUpdate *q;
+	while ((q = m_queue_in.pop())) {
 
 		ScopeProfiler sp(g_profiler, "Client: Mesh making");
 
@@ -196,10 +187,6 @@ void * MeshUpdateThread::Thread()
 
 		delete q;
 	}
-
-	END_DEBUG_EXCEPTION_HANDLER(errorstream)
-
-	return NULL;
 }
 
 /*
@@ -230,7 +217,7 @@ Client::Client(
 	m_nodedef(nodedef),
 	m_sound(sound),
 	m_event(event),
-	m_mesh_update_thread(this),
+	m_mesh_update_thread(),
 	m_env(
 		new ClientMap(this, this, control,
 			device->getSceneManager()->getRootSceneNode(),
@@ -1600,7 +1587,7 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
 	}
 
 	// Add task to queue
-	m_mesh_update_thread.m_queue_in.addBlock(p, data, ack_to_server, urgent);
+	m_mesh_update_thread.enqueueUpdate(p, data, ack_to_server, urgent);
 }
 
 void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server, bool urgent)
diff --git a/src/client.h b/src/client.h
index 474daf3bc..efd373e42 100644
--- a/src/client.h
+++ b/src/client.h
@@ -113,23 +113,27 @@ struct MeshUpdateResult
 	}
 };
 
-class MeshUpdateThread : public JThread
+class MeshUpdateThread : public UpdateThread
 {
+private:
+	MeshUpdateQueue m_queue_in;
+
+protected:
+	const char *getName()
+	{ return "MeshUpdateThread"; }
+	virtual void doUpdate();
+
 public:
 
-	MeshUpdateThread(IGameDef *gamedef):
-		m_gamedef(gamedef)
+	MeshUpdateThread()
 	{
 	}
 
-	void * Thread();
-
-	MeshUpdateQueue m_queue_in;
+	void enqueueUpdate(v3s16 p, MeshMakeData *data,
+			bool ack_block_to_server, bool urgent);
 
 	MutexedQueue<MeshUpdateResult> m_queue_out;
 
-	IGameDef *m_gamedef;
-
 	v3s16 m_camera_offset;
 };
 
diff --git a/src/minimap.cpp b/src/minimap.cpp
index 02660f969..8fe8b466d 100644
--- a/src/minimap.cpp
+++ b/src/minimap.cpp
@@ -105,67 +105,31 @@ QueuedMinimapUpdate * MinimapUpdateQueue::pop()
 	Minimap update thread
 */
 
-void MinimapUpdateThread::Stop()
-{
-	JThread::Stop();
-
-	// give us a nudge
-	m_queue_sem.Post();
-}
-
 void MinimapUpdateThread::enqueue_Block(v3s16 pos, MinimapMapblock *data)
 {
-	if (m_queue.addBlock(pos, data))
-		// we had to allocate a new block
-		m_queue_sem.Post();
+	m_queue.addBlock(pos, data);
+	deferUpdate();
 }
 
-void MinimapUpdateThread::forceUpdate()
+void MinimapUpdateThread::doUpdate()
 {
-	m_queue_sem.Post();
-}
-
-void *MinimapUpdateThread::Thread()
-{
-	ThreadStarted();
-
-	log_register_thread("MinimapUpdateThread");
-
-	DSTACK(__FUNCTION_NAME);
-
-	BEGIN_DEBUG_EXCEPTION_HANDLER
-
-	porting::setThreadName("MinimapUpdateThread");
-
-	while (!StopRequested()) {
-
-		m_queue_sem.Wait();
-		if (StopRequested()) break;
-
-		while (m_queue.size()) {
-			QueuedMinimapUpdate *q = m_queue.pop();
-			if (!q)
-				break;
-			std::map<v3s16, MinimapMapblock *>::iterator it;
-			it = m_blocks_cache.find(q->pos);
-			if (q->data) {
-				m_blocks_cache[q->pos] = q->data;
-			} else if (it != m_blocks_cache.end()) {
-				delete it->second;
-				m_blocks_cache.erase(it);
-			}
+	while (m_queue.size()) {
+		QueuedMinimapUpdate *q = m_queue.pop();
+		std::map<v3s16, MinimapMapblock *>::iterator it;
+		it = m_blocks_cache.find(q->pos);
+		if (q->data) {
+			m_blocks_cache[q->pos] = q->data;
+		} else if (it != m_blocks_cache.end()) {
+			delete it->second;
+			m_blocks_cache.erase(it);
 		}
-
-		if (data->map_invalidated) {
-			if (data->mode != MINIMAP_MODE_OFF) {
-				getMap(data->pos, data->map_size, data->scan_height, data->radar);
-				data->map_invalidated = false;
-			}
+	}
+	if (data->map_invalidated) {
+		if (data->mode != MINIMAP_MODE_OFF) {
+			getMap(data->pos, data->map_size, data->scan_height, data->radar);
+			data->map_invalidated = false;
 		}
 	}
-	END_DEBUG_EXCEPTION_HANDLER(errorstream)
-
-	return NULL;
 }
 
 MinimapUpdateThread::~MinimapUpdateThread()
@@ -177,7 +141,7 @@ MinimapUpdateThread::~MinimapUpdateThread()
 	}
 }
 
-MinimapPixel *MinimapUpdateThread::getMinimapPixel (v3s16 pos, s16 height, s16 &pixel_height)
+MinimapPixel *MinimapUpdateThread::getMinimapPixel(v3s16 pos, s16 height, s16 &pixel_height)
 {
 	pixel_height = height - MAP_BLOCKSIZE;
 	v3s16 blockpos_max, blockpos_min, relpos;
@@ -198,7 +162,7 @@ MinimapPixel *MinimapUpdateThread::getMinimapPixel (v3s16 pos, s16 height, s16 &
 	return NULL;
 }
 
-s16 MinimapUpdateThread::getAirCount (v3s16 pos, s16 height)
+s16 MinimapUpdateThread::getAirCount(v3s16 pos, s16 height)
 {
 	s16 air_count = 0;
 	v3s16 blockpos_max, blockpos_min, relpos;
@@ -215,7 +179,7 @@ s16 MinimapUpdateThread::getAirCount (v3s16 pos, s16 height)
 	return air_count;
 }
 
-void MinimapUpdateThread::getMap (v3s16 pos, s16 size, s16 height, bool radar)
+void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height, bool radar)
 {
 	v3s16 p = v3s16 (pos.X - size / 2, pos.Y, pos.Z - size / 2);
 
@@ -327,7 +291,7 @@ void Mapper::setMinimapMode(MinimapMode mode)
 	data->scan_height = modeDefs[(int)mode * 3 + 1];
 	data->map_size = modeDefs[(int)mode * 3 + 2];
 	data->mode = mode;
-	m_minimap_update_thread->forceUpdate();
+	m_minimap_update_thread->deferUpdate();
 }
 
 void Mapper::setPos(v3s16 pos)
@@ -336,7 +300,7 @@ void Mapper::setPos(v3s16 pos)
 	if (pos != data->old_pos) {
 		data->old_pos = data->pos;
 		data->pos = pos;
-		m_minimap_update_thread->forceUpdate();
+		m_minimap_update_thread->deferUpdate();
 	}
 }
 
diff --git a/src/minimap.h b/src/minimap.h
index 37bc2f7cb..3cb7da898 100644
--- a/src/minimap.h
+++ b/src/minimap.h
@@ -96,7 +96,6 @@ public:
 
 	bool addBlock(v3s16 pos, MinimapMapblock *data);
 
-	// blocking!!
 	QueuedMinimapUpdate *pop();
 
 	u32 size()
@@ -110,12 +109,16 @@ private:
 	JMutex m_mutex;
 };
 
-class MinimapUpdateThread : public JThread
+class MinimapUpdateThread : public UpdateThread
 {
 private:
-	JSemaphore m_queue_sem;
 	MinimapUpdateQueue m_queue;
 
+protected:
+	const char *getName()
+	{ return "MinimapUpdateThread"; }
+	virtual void doUpdate();
+
 public:
 	MinimapUpdateThread(IrrlichtDevice *device, Client *client)
 	{
@@ -131,13 +134,10 @@ public:
 	video::SColor getColorFromId(u16 id);
 
 	void enqueue_Block(v3s16 pos, MinimapMapblock *data);
-	void forceUpdate();
 	IrrlichtDevice *device;
 	Client *client;
 	video::IVideoDriver *driver;
 	ITextureSource *tsrc;
-	void Stop();
-	void *Thread();
 	MinimapData *data;
 	std::map<v3s16, MinimapMapblock *> m_blocks_cache;
 };
diff --git a/src/util/thread.h b/src/util/thread.h
index eda9c0ca2..faa5869ca 100644
--- a/src/util/thread.h
+++ b/src/util/thread.h
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "../jthread/jmutex.h"
 #include "../jthread/jmutexautolock.h"
 #include "porting.h"
+#include "log.h"
 
 template<typename T>
 class MutexedVariable
@@ -208,5 +209,65 @@ private:
 	MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
 };
 
+class UpdateThread : public JThread
+{
+private:
+	JSemaphore m_update_sem;
+
+protected:
+	virtual void doUpdate() = 0;
+	virtual const char *getName() = 0;
+
+public:
+	UpdateThread()
+	{
+	}
+	~UpdateThread()
+	{}
+
+	void deferUpdate()
+	{
+		m_update_sem.Post();
+	}
+
+	void Stop()
+	{
+		JThread::Stop();
+
+		// give us a nudge
+		m_update_sem.Post();
+	}
+
+	void *Thread()
+	{
+		ThreadStarted();
+
+		const char *thread_name = getName();
+
+		log_register_thread(thread_name);
+
+		DSTACK(__FUNCTION_NAME);
+
+		BEGIN_DEBUG_EXCEPTION_HANDLER
+
+		porting::setThreadName(thread_name);
+
+		while (!StopRequested()) {
+
+			m_update_sem.Wait();
+
+			// Empty the queue, just in case doUpdate() is expensive
+			while (m_update_sem.GetValue()) m_update_sem.Wait();
+
+			if (StopRequested()) break;
+
+			doUpdate();
+		}
+		END_DEBUG_EXCEPTION_HANDLER(errorstream)
+
+		return NULL;
+	}
+};
+
 #endif