Thread Safety

There are a number of different concerns application authors should think about when using WebSocket++ in multithreaded applications. All of the information below applies to WebSocket++ 0.3.x and later. Users of 0.2.x are best served by running WebSocket++ in its own thread and communicating only via the handlers.

Endpoint Thread Safety

WebSocket++ contains no non-static const global state. Distinct endpoints in separate threads will not interfere with each other. The extent to which individual endpoint methods are thread safe depends on several of the config policy choices. The primary ones that affect thread safety are as follows:

Concurrency Policy

A WebSocket++ endpoint's config includes a concurrency policy. This policy defines a set of mutexes, condition variables, and locks that WebSocket++ core will use to implement endpoint thread safety and handler serialization guarantees. WebSocket++ core includes two concurrency policies:

websocketpp::concurrency::basic

This policy selects between Boost and C++11 concurrency primitives based on what is available. It is the default policy.

websocketpp::concurrency::none

This is a stub policy that reduces all concurrency primitives to noops. Using the concurrency::none policy will remove the overhead of locking and synchronization in single threaded environments. Such an environment must be able to guarantee that all access to endpoint methods and connection_hdls are externally serialized. This mode does not require the program itself be single threaded. Either a global lock for each endpoint or running all endpoint communication and handlers in a single thread will satisfy the requirements.

Transport Policy

The transport policy used has a large effect on the thread safety of WebSocket++. Each transport is responsible for implementing its own thread safety. All core transports serialize handlers for a given connection assuming that a non-stub concurrency policy and that all of the other requirements described below are met. Some policies also provide thread safe access to all endpoint methods. Specific thread safety properties and requirements:

transport::iostream

The iostream transport serializes incoming reads. It is otherwise not thread safe. Calling endpoint methods, such as endpoint.send(), while a read is in flight in another thread results in undefined behavior. To avoid this, the application must manually serialize calls to endpoint methods.

transport::asio

The Asio transport provides full thread safety for endpoint. Works with an io_service thread pool where multiple threads are calling io_service.run();

Connection Thread Safety

All core transports guarantee that the handlers for a given connection will be serialized. When the transport and concurrency policies support endpoint concurrency, anything involving a connection_hdl should be thread safe. i.e. It is safe to pass connection_hdls to other threads, store them indefinitely, and call endpoint methods that take them as parameters from any thread at any time.

Individual connection objects are never thread safe for access from outside threads and are only safe for use in handlers in specific cases. Those cases are when a handler uses endpoint.get_con_from_hdl() to upgrade its own connection_hdl to a full connection_ptr. This pointer can then be used safely to interact directly with the connection for the remainder of that handler. Upgraded connection_ptrs should not be passed to other threads or retained beyond the end of the handler in which it was converted. A handler for a given connection should not convert and use a connection_ptr to another connection. Endpoint methods should be used to send a message or interact with another connection from within a handler.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.