Make Message and Client pools thread-safe using ConcurrentDictionary#180
Open
CrossV4 wants to merge 1 commit into
Open
Make Message and Client pools thread-safe using ConcurrentDictionary#180CrossV4 wants to merge 1 commit into
CrossV4 wants to merge 1 commit into
Conversation
…and ConcurrentStack for avoiding calling Update function from another thread.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of Changes
I have developed a highly efficient, multi-threaded, and thread-safe networking architectural pattern for RiptideNetworking, specifically designed for high-concurrency projects like MMORPGs.
The Problem: Thread Contention & Race Conditions
When offloading network I/O operations to a dedicated background thread (e.g., executing
Server.Update()asynchronously to keep the main game loop responsive), serious race conditions occur. The primary culprit is Riptide’s internal message pool (Message.Create(),Message.Release()). Accessing the message pool concurrently from both the Main Thread (Game Logic) and the Background Thread (Network Loop) corrupts internal byte arrays, leading to network desynchronization, corrupted data, and server crashes.The Solution: The Command Pattern & Asynchronous Action Queue
To bridge the gap between the Main Thread and the Network Thread safely without expensive resource locking, I implemented a custom Command Pattern execution pipeline combined with a
ConcurrentQueue.INetworkCommandstructures and enqueue them into a thread-safeConcurrentQueue.Update()loop. To ensure server stability and prevent CPU spikes caused by a massive surge of packets, I integrated a Frame Budget Monitor using aStopwatch. If processing takes longer than the allocated frame time budget(MaxFrameMs), the execution breaks, deferred actions are carried over to the next frame, and a warning is logged.Server.Update()runs continuously on a high-priority background worker thread, throttled naturally to prevent CPU core exhaustion.Message message = Message.Create(MessageSendMode.Reliable, ServerToClientId.PromoResult);Why This is Vital for the Community
By enforcing this design, Riptide’s pooling mechanism (Message.Create) is only ever touched from a single thread sequence during actual processing, completely eliminating Riptide-pool-related Multi-Thread crashes. I wanted to share this architectural solution with the Riptide community to help anyone struggling to transition their dedicated servers to an asynchronous, high-performance, and crash-proof multi-threaded environment. Hope it helps!