Add UpdateThread and use it for minimap and mesh threads
authorest31 <MTest31@outlook.com>
Mon, 29 Jun 2015 09:06:03 +0000 (11:06 +0200)
committerest31 <MTest31@outlook.com>
Mon, 29 Jun 2015 13:00:19 +0000 (15:00 +0200)
src/client.cpp
src/client.h
src/minimap.cpp
src/minimap.h
src/util/thread.h

index ce48df953523d975e3f31134c909d3c4c5e5bedb..b02e6229c9902810c860bad115e31d94ae803afd 100644 (file)
@@ -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)
index 474daf3bc527a2a7a5f6d1e540b7c37f2385b0e1..efd373e4266db7f707414f0082b73deb223ed182 100644 (file)
@@ -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;
 };
 
index 02660f969fe892e2f89ced604a52b39deb12a866..8fe8b466d40a4cd985372d45d7717688b29618c1 100644 (file)
@@ -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();
        }
 }
 
index 37bc2f7cb81d64d31a4e42eab7edb93f23cf9c77..3cb7da898359d196358d8848ac2120d77714b747 100644 (file)
@@ -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;
 };
index eda9c0ca2021193fe1ebdb912aabbea221311ac9..faa5869ca8981bc5aa44e0e1964fead235abe71a 100644 (file)
@@ -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