There's something that is bothering me in MCServer: There is no thread that is the real owner of the world data. There are CriticalSections locking things all over the place. Any thread can just access the blocks in a world or manipulate entities and players whenever it likes.
I suggest making it so that the world data can only be accessed by a single thread and get rid of all the CriticalSections. The most logical thread that comes to my mind is the Tick thread.
In order to still access the world data from other threads we can add a function to cWorld, RunOnTickThread(). It has a callback as a parameter and that callback will be executed on the Tick thread while it is idle (after it has ticked the world, entities, etc.). The Tick thread will have a queue of these callbacks that will be executed in the order they were added. This way we will only need a single CriticalSection. This CriticalSection will protect the queue of callbacks.
There should be no performance penalty by doing this. The way it is right now the world data can only be accessed by one thread at a time as well. The only thing this solution does is make sure the data is always accessed by the same thread instead of several different threads.
As far as I know this solution should work fine and will make data ownership much clearer. There is however one problem I know of right now.. sigh.. plugins.
Lua plugins (like the world data) can only be accessed by a single thread at a time. A single plugin cannot be accessed by multiple threads so the callback method will not work the way it is now. The callback will always be executed by the Tick thread, while the OnChat function for example might be called from the Socket threads. The Socket thread will lock the plugin, the plugin requests execution on the Tick thread and you got a deadlock.
A solution to the plugin problem is using yield functions (https://forum.cuberite.org/showthread.php?tid=768) which allows a thread to give up ownership of the plugin while another thread is accessing it. This solution works, but in my opinion this is a bad solution for the same reason I created this thread. A plugin can only be accessed by one thread at a time, why not make a thread owner of the plugin?
The better solution for the plugins is in my opinion to also make sure it is always executed from the same thread and get rid of the CriticalSections surrounding them. Plugins tend to change/enhance gameplay and interact with the world and players so the most logical thread to give ownership of the plugins to is the Tick thread as well.
Any thoughts on this?
I suggest making it so that the world data can only be accessed by a single thread and get rid of all the CriticalSections. The most logical thread that comes to my mind is the Tick thread.
In order to still access the world data from other threads we can add a function to cWorld, RunOnTickThread(). It has a callback as a parameter and that callback will be executed on the Tick thread while it is idle (after it has ticked the world, entities, etc.). The Tick thread will have a queue of these callbacks that will be executed in the order they were added. This way we will only need a single CriticalSection. This CriticalSection will protect the queue of callbacks.
There should be no performance penalty by doing this. The way it is right now the world data can only be accessed by one thread at a time as well. The only thing this solution does is make sure the data is always accessed by the same thread instead of several different threads.
As far as I know this solution should work fine and will make data ownership much clearer. There is however one problem I know of right now.. sigh.. plugins.
Lua plugins (like the world data) can only be accessed by a single thread at a time. A single plugin cannot be accessed by multiple threads so the callback method will not work the way it is now. The callback will always be executed by the Tick thread, while the OnChat function for example might be called from the Socket threads. The Socket thread will lock the plugin, the plugin requests execution on the Tick thread and you got a deadlock.
A solution to the plugin problem is using yield functions (https://forum.cuberite.org/showthread.php?tid=768) which allows a thread to give up ownership of the plugin while another thread is accessing it. This solution works, but in my opinion this is a bad solution for the same reason I created this thread. A plugin can only be accessed by one thread at a time, why not make a thread owner of the plugin?
The better solution for the plugins is in my opinion to also make sure it is always executed from the same thread and get rid of the CriticalSections surrounding them. Plugins tend to change/enhance gameplay and interact with the world and players so the most logical thread to give ownership of the plugins to is the Tick thread as well.
Any thoughts on this?