boost::corosio::tcp_server
TCP server with pooled workers.
Synopsis
Declared in <boost/corosio/tcp_server.hpp>
class tcp_server;
Description
This class manages a pool of reusable worker objects that handle incoming connections. When a connection arrives, an idle worker is dispatched to handle it. After the connection completes, the worker returns to the pool for reuse, avoiding allocation overhead per connection.
Workers are set via set_workers as a forward range of pointer‐like objects (e.g., unique_ptr<worker_base>). The server takes ownership of the container via type erasure.
Lifecycle
The server operates in three states:
‐ Stopped: Initial state, or after join completes. ‐ Running: After start, actively accepting connections. ‐ Stopping: After stop, draining active work.
State transitions:
[Stopped] --start()--> [Running] --stop()--> [Stopping] --join()--> [Stopped]
Running the Server
io_context ioc;
tcp_server srv(ioc, ioc.get_executor());
srv.set_workers(make_workers(ioc, 100));
srv.bind(endpoint{address_v4::any(), 8080});
srv.start();
ioc.run(); // Blocks until all work completes
Graceful Shutdown
To shut down gracefully, call stop then drain the io_context:
// From a signal handler or timer callback:
srv.stop();
// ioc.run() returns after pending work drains.
// Then from the thread that called ioc.run():
srv.join(); // Wait for accept loops to finish
Restart After Stop
The server can be restarted after a complete shutdown cycle. You must drain the io_context and call join before restarting:
srv.start();
ioc.run_for( 10s ); // Run for a while
srv.stop(); // Signal shutdown
ioc.run(); // REQUIRED: drain pending completions
srv.join(); // REQUIRED: wait for accept loops
// Now safe to restart
srv.start();
ioc.run();
WARNING: What NOT to Do
‐ Do NOT call join from inside a worker coroutine (deadlock). ‐ Do NOT call join from a thread running ioc.run() (deadlock). ‐ Do NOT call start without completing join after stop. ‐ Do NOT call ioc.stop() for graceful shutdown; use stop instead.
Example
class my_worker : public tcp_server::worker_base
{
corosio::tcp_socket sock_;
capy::any_executor ex_;
public:
my_worker(io_context& ctx)
: sock_(ctx)
, ex_(ctx.get_executor())
{
}
corosio::tcp_socket& socket() override { return sock_; }
void run(launcher launch) override
{
launch(ex_, [](corosio::tcp_socket* sock) -> capy::task<>
{
// handle connection using sock
co_return;
}(&sock_));
}
};
auto make_workers(io_context& ctx, int n)
{
std::vector<std::unique_ptr<tcp_server::worker_base>> v;
v.reserve(n);
for(int i = 0; i < n; ++i)
v.push_back(std::make_unique<my_worker>(ctx));
return v;
}
io_context ioc;
tcp_server srv(ioc, ioc.get_executor());
srv.set_workers(make_workers(ioc, 100));
Types
Name |
Description |
Move‐only handle to launch a worker coroutine. |
|
Abstract base class for connection handlers. |
Member Functions
Name |
Description |
|
Construct a TCP server. |
|
Destructor |
|
Assignment operators |
Bind to a local endpoint. |
|
Block until all accept loops complete. |
|
Set the worker pool. |
|
Start accepting connections. |
|
Stop accepting connections. |
See Also
worker_base, set_workers, launcher
Created with MrDocs