I'm writing up a game server on which thread-safety is very important, basically for this approach I've decided to move my entire server in a single brain loop which handles everything in a single thread, connections are ran separately in their own separate thread, whenever a packet is received, the brain loop is signaled so it doesn't have to wait for the entire interval.
This is truly the best approach I could come up with, given my server is filled with pointers everywhere, and invalidation would kill my player base.
#define GAME_BEAT 50
void Game::brain() {
int64_t connectionsTimeCounter = 0;
int64_t decayTimeCounter = 0;
int64_t releasePointersCounter = 0;
int64_t creaturesTimeCounter = 0;
int64_t roundNr = getServerMilliseconds();
while (isGameRunning() || isGameStarting()) {
gameSignal.wait(GAME_BEAT);
int64_t delay = getServerMilliseconds() - roundNr;
roundNr = getServerMilliseconds();
// Receive packets from connections with data available to be read (non-blocking)
// when data is available to be read, the connection which was previously ran in a different thread
// will be signaled to read packet data and store it in a variable
// say, a packet for "player talk" was sent, then the function below "moveCreatures" would handle this action
g_server.receiveData();
connectionsTimeCounter += delay;
if (connectionsTimeCounter >= 1000) {
// This function closes invalid connections/closed connections
g_server.processConnections();
}
decayTimeCounter += delay;
if (connectionsTimeCounter >= 1500) {
decayItems(delay);
}
releasePointersCounter += delay;
if (releasePointersCounter >= 1000) {
// This function simply calls a "delete" to removed objects from the game
releaseObjects();
}
creaturesTimeCounter += delay;
if (creaturesTimeCounter >= 1000) {
// Processes creatures idle status
processCreatures(delay);
}
// Moves creatures, players, talking, moving, etc ...
moveCreatures();
// Sends all pending packets to be sent to active connections
g_server.sendAllData();
}
}
That is pretty much the only way I found for my server to be thread-safe, since I did experienced a few crashes because when connections sent a particular packet (say player move item), it would invalidate other connections from doing so
moveCreatures()doesn't just move creatures/players but makes them talk? anything else? is it worth reconsidering a different name for this method? like PeformNPCAction or PerformAction? etc.. \$\endgroup\$