Beast Logo

PrevUpHomeNext

Notes

Because calls to read data may return a variable amount of bytes, the interface to calls that read data require an object that meets the requirements of DynamicBuffer. This concept is modeled on boost::asio::streambuf.

The implementation does not perform queueing or buffering of messages. If desired, these features should be provided by callers. The impact of this design is that library users are in full control of the allocation strategy used to store data and the back-pressure applied on the read and write side of the underlying TCP/IP connection.

Asynchronous Operations

Asynchronous versions are available for all functions:

multi_buffer buffer;
ws.async_read(buffer,
    [](error_code)
    {
        // Do something with the buffer
    });

Calls to asynchronous initiation functions support the extensible asynchronous model developed by the Boost.Asio author, allowing for traditional completion handlers, stackful or stackless coroutines, and even futures:

void echo(stream<boost::asio::ip::tcp::socket>& ws,
    multi_buffer& buffer, boost::asio::yield_context yield)
{
    ws.async_read(buffer, yield);
    std::future<void> fut =
        ws.async_write(buffer.data(), boost::asio::use_future);
}
The io_service

The creation and operation of the io_service associated with the underlying stream is left to the callers, permitting any implementation strategy including one that does not require threads for environments where threads are unavailable. Beast WebSocket itself does not use or require threads.

Thread Safety

Like a regular Boost.Asio socket, a stream is not thread safe. Callers are responsible for synchronizing operations on the socket using an implicit or explicit strand, as per the Asio documentation. The asynchronous interface supports one active read and one active write simultaneously. Undefined behavior results if two or more reads or two or more writes are attempted concurrently. Caller initiated WebSocket ping, pong, and close operations each count as an active write.

The implementation uses composed asynchronous operations internally; a high level read can cause both reads and writes to take place on the underlying stream. This behavior is transparent to callers.


PrevUpHomeNext