|
The more common setup I've seen is using a handful of worker threads and queueing work to thread safe collections to be processed.
Async sockets are going to be using a background threadpool to handle their data. You can then queue up waiting data to be processed. Often the work of processing will be split into a handful of worker threads to minimize context switching and to try to keep everything that could conflict on the same thread.
For example... lets say you have a thread that handles all database logic, it makes sense that when you go to save a value (lets say saving a character when they log out) to switch all of the work to that single database thread. it ensures that (hopefully) you avoid race conditions and you don't lock up a separate thread that might have other work waiting.
The same can be done for things like all entity updates (status effects, timed actions, etc), for monster background AI (NOT triggering the actual actions, just planning it out), for all battle or map functions, for packet processing or for a handful of other things.
This doesn't mean you don't have to take into account thread safety in your collections but you can at least try to limit the number of times that threads could be conflicting with eachother and try to split the work into manageable sections.
I'm not super familiar with how well thread priorities work but it's something you might want to look into as well. Things like saving to database, planning future monster movement paths and other stuff like that don't need to be as high priority as say... processing a player movement packet. By having them split to their own worker thread you may have the possibility of shifting around their priority (I'm guessing though that it may be best to leave that up to the OS to manage)
|