I\'m working on a project that involves a boost::beast
websocket/http mixed server, which runs on top of boost::asio
. I\'ve heavily based my projec
The answer from @sehe was amazing, so I'll be brief. Generally speaking, to implement an algorithm which operates on all active connections you must do the following:
Maintain a list of active connections. If this list is accessed by multiple threads, it will need synchronization (std::mutex
). New connections should be inserted to the list, and when a connection is destroyed or becomes inactive it should be removed from the list.
To iterate the list, synchronization is required if the list is accessed by multiple threads (i.e. more than one thread calling asio::io_context::run
, or if the list is also accessed from threads that are not calling asio::io_context::run
)
During iteration, if the algorithm needs to inspect or modify the state of any connection, and that state can be changed by other threads, additional synchronization is needed. This includes any internal "queue" of messages that the connection object stores.
A simple way to synchronize a connection object is to use boost::asio::post
to submit a function for execution on the connection object's context, which will be either an explicit strand (boost::asio::strand
, as in the advanced server examples) or an implicit strand (what you get when only one thread calls io_context::run
). The Approach 1 provided by @sehe uses post
to synchronize in this fashion.
Another way to synchronize the connection object is to "stop the world." That means call io_context::stop
, wait for all the threads to exit, and then you are guaranteed that no other threads are accessing the list of connections. Then you can read and write connection object state all you want. When you are finished with the list of connections, call io_context::restart
and launch the threads which call io_context::run
again. Stopping the io_context
does not stop network activity, the kernel and network drivers still send and receive data from internal buffers. TCP/IP flow control will take care of things so the application still operates smoothly even though it becomes briefly unresponsive during the "stop the world." This approach can simplify things but depending on your particular application you will have to evaluate if it is right for you.
Hope this helps!