Hello, I've been thinking about ways to eliminate threading / locking issues, and I had this idea.
Forgive me if this has been discussed before. Also, if the technique I'm about to describe has a common name in the C++ world, I'd be glad to hear it. I've done some searching but found no such name.
The idea is based on old school message passing, but it's enhanced with lambdas.
Reminder of old-school message-passing: Each thread has a single inbox, similar to our World::m_PlayersToAdd. Other threads can send messages to that inbox. The thread periodically checks the inbox, and acts accordingly. The neat thing here is that only one single lock is required per thread (to prevent reading and writing to the inbox at the same time), and concurrency is very clean.
Traditionally, the downside is that one would need to create some sort of messaging system. e.g. each message has an ID which the consuming thread reads and determines the message type accordingly, etc.
With lambdas, this is no longer a problem: Each thread's inbox is a queue of lambdas, threads send lambdas to each other, concurrency is perfect, code is clean.
Example pseudocode for transferring an entity from one world thread to another world thread:
Example pseudocode for a cClientHandle removing a player safely (Currently player removal is NOT thread safe, see this)
Example inbox processing, that's just about all the concurrency code we need:
Thoughts?
Forgive me if this has been discussed before. Also, if the technique I'm about to describe has a common name in the C++ world, I'd be glad to hear it. I've done some searching but found no such name.
The idea is based on old school message passing, but it's enhanced with lambdas.
Reminder of old-school message-passing: Each thread has a single inbox, similar to our World::m_PlayersToAdd. Other threads can send messages to that inbox. The thread periodically checks the inbox, and acts accordingly. The neat thing here is that only one single lock is required per thread (to prevent reading and writing to the inbox at the same time), and concurrency is very clean.
Traditionally, the downside is that one would need to create some sort of messaging system. e.g. each message has an ID which the consuming thread reads and determines the message type accordingly, etc.
With lambdas, this is no longer a problem: Each thread's inbox is a queue of lambdas, threads send lambdas to each other, concurrency is perfect, code is clean.
Example pseudocode for transferring an entity from one world thread to another world thread:
cEntity::NewDoMoveToWorld(cWorld & a_NewWorld) { ...Code here... m_World.RemoveEntity(this); a_NewWorld.message([this](cWorld & a_World) -> void { a_World.AddEntity(this); // This is threadsafe, because the world will execute it when it processes the inbox. } }
Example pseudocode for a cClientHandle removing a player safely (Currently player removal is NOT thread safe, see this)
cClientHandle:: Destroy() { ...Code here... m_Player.GetWorld().message([m_Player](cWorld & a_World) -> void { a_World.RemovePlayer(m_Player); } }
Example inbox processing, that's just about all the concurrency code we need:
cworld::tick() { ...Code here... { cCSLock Lock(m_InboxLock); for (message : m_Inbox) { message(*this); } if (Inbox.size() > 0) Inbox.clear(); } } cWorld::message(std::function<void(cWorld & a_World)> a_Message) { cCSLock Lock(m_InboxLock); m_Inbox.push_back(a_Message); }
Thoughts?