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(); + m_queue_in.addBlock(p, data, ack_block_to_server, urgent); + deferUpdate(); +} - log_register_thread("MeshUpdateThread"); - - DSTACK(__FUNCTION_NAME); - - BEGIN_DEBUG_EXCEPTION_HANDLER - - porting::setThreadName("MeshUpdateThread"); - - 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 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::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; - } + while (m_queue.size()) { + QueuedMinimapUpdate *q = m_queue.pop(); + std::map::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; } } - 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 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 class MutexedVariable @@ -208,5 +209,65 @@ private: MutexedQueue< GetRequest > 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