My proposal does not change that it is accessed sequentially, it simply makes it more clear. If you run a command through a function called RunOnTickThread() you know exactly what is going to happen, it will be executed sequentially on the Tick thread. Right now a person might think setting blocks is done in parallel while in reality threads are stalling.
My solution to this confusion simply makes things much easier to comprehend. The chunkmap will only be accessed by the same thread, always, so we can get rid of all the CriticalSections surrounding it.
Alright, some pseudocode. Imagine that worlds have their own thread already.
My solution to this confusion simply makes things much easier to comprehend. The chunkmap will only be accessed by the same thread, always, so we can get rid of all the CriticalSections surrounding it.
Alright, some pseudocode. Imagine that worlds have their own thread already.
class cWorld { public: // ... void RunOnTickThread(cCallback* a_pCommand) { if (GetCurrentThreadId() == GetTickThreadId()) { a_pCommand->Run(); return; } m_CommandQueueCS.Lock(); m_CommandQueue.push_back(a_pCommand); m_CommandQueueEvent.Set(); m_CommandQueueCS.Unlock(); a_pCommand->GetDoneEvent().Wait(); } cCallback* GetNextCommand() { cCSLock(m_CommandQueueCS); if (m_CommandQueue.empty()) return NULL; // CCommand* Command = m_CommandQueue.front(); m_CommandQueue.pop_front(); return Command; } // ... private: cEvent m_CommandQueueEvent; cCriticalSection m_CommandQueueCS; std::vector<cCallback*> m_CommandQueue; }; void cWorld::TickThread() { cTimer Timer; long long msPerTick = 50; long long LastTime = Timer.GetNowTime(); while (...) { // Update world long long NowTime = Timer.GetNowTime(); float DeltaTime = (float)(NowTime-LastTime); TickWorld(DeltaTime); long long TickTime = Timer.GetNowTime() - NowTime; // Handle command queue long long CommandTimeLeft = msPerTick - TickTime; do { long long BeforeCommandTime = Timer.GetNowTime(); // while (cCallback* c = GetNextCommand()) { c->Run(); c->GetDoneEvent().Set(); } // long long CommandDuration = Timer.GetNowTime() - BeforeCommandTime; CommandTimeLeft -= CommandDuration; } while(m_CommandQueueEvent.Wait(MAX(CommandTimeLeft,0)) != TIMED_OUT); LastTime = NowTime; } }