// Returned pointer must be deleted
// Returns NULL if queue is empty
-QueuedMeshUpdate * MeshUpdateQueue::pop()
+QueuedMeshUpdate *MeshUpdateQueue::pop()
{
JMutexAutoLock lock(m_mutex);
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");
delete q;
}
-
- END_DEBUG_EXCEPTION_HANDLER(errorstream)
-
- return NULL;
}
/*
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(),
}
// 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)
}
};
-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;
};
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()
}
}
-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;
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;
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);
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)
if (pos != data->old_pos) {
data->old_pos = data->pos;
data->pos = pos;
- m_minimap_update_thread->forceUpdate();
+ m_minimap_update_thread->deferUpdate();
}
}
bool addBlock(v3s16 pos, MinimapMapblock *data);
- // blocking!!
QueuedMinimapUpdate *pop();
u32 size()
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)
{
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;
};
#include "../jthread/jmutex.h"
#include "../jthread/jmutexautolock.h"
#include "porting.h"
+#include "log.h"
template<typename T>
class MutexedVariable
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