#include <x/fdlistener.H> class myServerThread : virtual public x::obj { public: void run(const x::fd &raw_socket, const x::fd &termfd) { raw_socket->nonblock(true); x::fdtimeout socket(x::fdtimeout::create(raw_socket)); socket->set_terminate_fd(termfd); // read and write from socket. } }; x::ref<myServerThread> server(x::ref<myServerThread>::create()); x::fdlistener listener(x::fdlistener::create(4000)); listener->start(server); // ... listener->stop(); listener->wait();
x::fdlistener
is a reference to
a reference-counted object that implements a thread which listens on one
or more sockets for incoming connections, starting a new thread for
each established connection.
create
() creates a new listener object.
Its parameter may be one of the following:
A listening SOCK_STREAM
socket is created,
bound to this port, and
listen(3)d on.
A listening SOCK_STREAM
socket is created
for each port in the given list, separated by commas or spaces.
Each file descriptor is bound to the port and
listen(3)d on.
std::list<int>
A listening SOCK_STREAM
socket is created
for multiple port numbers specified by the given list.
Each socket is bound to a port and
listen(3)d on.
std::list<x::fd>
This is presumed to be a list of file descriptors that have already been bound to their appropriate ports. Each file descriptor in the list is listen(3)d on.
create
() also takes several optional parameters for
its internal thread worker, which are described
in the worker pool documentation.
The constructor instantiates an object.
start
() spawns a thread that accepts connections
from listening sockets, and starts other threads, for each accepted
connection. The parameter to
start
() is a reference to an object
that defines a run
() method, as given in the
example above. run
() gets invoked for each accepted
connection, in its own separate thread, and all connection threads
use the same server object's
run
() method.
The first parameter to run
() is a reference to
a file descriptor object for the new socket.
The second parameter is a reference to a
terminator file descriptor.
This file descriptor becomes readable if the connection thread
is still running when the listener thread stops.
The connection thread should terminate when the terminator file descriptor becomes readable. The above example demonstrates the direct approach of directly setting it as a file descriptor terminator for the raw socket.
The run
() method may also take additional
parameters that get forwarded by the listener object's
start
():
#include <x/fdlistener.H> class documentObj; typedef x::ref<documentObj> document; class myServerThread : virtual public x::obj { public: void run(const x::fd &raw_socket, const x::fd &termfd, const document &doc) { raw_socket->nonblock(true); x::fdtimeout socket(x::fdtimeout::create(raw_socket)); socket->set_terminate_fd(termfd); // read and write from socket. } }; x::ref<myServerThread> server(x::ref<myServerThread>::create()); x::fdlistener listener(x::fdlistener::create(4000)); listener->start(server, document::create());
The additional parameters to the listener object's
start
() get forwarded as additional parameters
to the server object's run
().
The same parameters given to start
() get
forwarded to each thread that gets started for each accepted connection.
The parameters given to start
() get saved.
The parameters must be copy-constructible. Each started thread
is passed a copy of the same saved parameter values.
Only one copy of the stored parameters gets saved. Each thread gets
a reference to a constant parameter value.
The thread's run
() must declare the forwarded
parameter types as rvalues or as references to constant types.