A utility class for making I/O handling in non-blocking libev evented servers much easier. More...
#include <EventedClient.h>
Inherited by Passenger::EventedMessageClient.
Public Member Functions | |
EventedClient (struct ev_loop *loop, const FileDescriptor &_fd) | |
Creates a new EventedClient with the given libev loop and file descriptor. | |
void | ref () |
Increase reference count. | |
void | unref () |
Decrease reference count. | |
bool | ioAllowed () const |
Returns whether it is allowed to perform any I/O with this client. | |
bool | readWatcherActive () const |
Used by unit tests. | |
size_t | pendingWrites () const |
Returns the number of bytes that are scheduled to be sent to the client at a later time. | |
void | notifyReads (bool enable) |
Sets whether you're interested in read events. | |
void | setOutboxLimit (unsigned int size) |
Sets a limit on the client outbox. | |
void | write (const StaticString data[], unsigned int count) |
Sends data to this client. | |
void | disconnect (bool force=false) |
Disconnects the client. | |
FileDescriptor | detach () |
Detaches the client file descriptor so that this EventedClient no longer has any control over it. | |
Public Attributes | |
FileDescriptor | fd |
The client's file descriptor. | |
Callback | onReadable |
Called when the file descriptor becomes readable and read notifications are enabled (see notifyRead() ). | |
Callback | onDisconnect |
Called when the client is disconnected. | |
Callback | onDetach |
Called when detach() is called for the first time. | |
Callback | onPendingDataFlushed |
Called after all pending outgoing data have been written out. | |
SystemErrorCallback | onSystemError |
System call errors are reported with this callback. | |
void * | userData |
EventedClient doesn't do anything with this. |
A utility class for making I/O handling in non-blocking libev evented servers much easier.
onDisconnect
).ref()
and unref()
).onReadable
callback.write()
method accepts an array of buffers. Whenever possible, all of these buffers are written out in the given order, using a single system call, without copying them into a single temporary buffer.setOutboxLimit()
).disconnect
method respects pending writes. It will disconnect after all pending outgoing data have been written out.Construct an EventedClient with a libev loop and a file descriptor:
EventedClient *client = new EventedClient(loop, fd);
You are probably interested in read readiness notifications on fd
. However these notifications are disabled by default. You need to set the onReadable
callback (which is called every time the fd is readable) and enable read notifications.
void onReadable(EventedClient *client) { // do whatever you want } ... client->onReadable = onReadable; client->notifyReads(true);
EventedClient never raises exceptions, except when your callbacks do. It reports errors with the onSystemError
callback. That said, EventedClient is exception-aware and will ensure that its internal state stays consistent even when your callbacks throw exceptions.
Passenger::EventedClient::EventedClient | ( | struct ev_loop * | loop, | |
const FileDescriptor & | _fd | |||
) | [inline] |
Creates a new EventedClient with the given libev loop and file descriptor.
The initial reference count is 1.
FileDescriptor Passenger::EventedClient::detach | ( | ) | [inline] |
Detaches the client file descriptor so that this EventedClient no longer has any control over it.
Any EventedClient I/O watchers on the client file descriptor will be stopped and further I/O on the file descriptor via EventedClient will become impossible. The original client file descriptor is returned and onDetach
is called. Subsequent calls to this function will return -1 and will no longer call onDetach
.
void Passenger::EventedClient::disconnect | ( | bool | force = false |
) | [inline] |
Disconnects the client.
This actually closes the underlying file descriptor, even if the FileDescriptor object still has references.
If force is true then the client will be disconnected immediately, and any pending outgoing data will be discarded. Otherwise the client will be disconnected after all pending outgoing data have been sent; in the mean time no new data can be received from or sent to the client.
After the client has actually been disconnected (which may be either immediately or after a short period of time), a disconnect event will be emitted.
If the client connection has already been closed then this method does nothing. If the client connection is being closed (because there's pending outgoing data) then the behavior depends on the force
argument: if true then the connection is closed immediately and the pending data is discarded, otherwise this method does nothing.
The onDisconnect
callback will be called after the file descriptor is closed, which is either immediately or after all pending data has been sent out.
bool Passenger::EventedClient::ioAllowed | ( | ) | const [inline] |
Returns whether it is allowed to perform any I/O with this client.
Usually true, and false when the client is either being disconnected or has been disconnected. A return value of false indicates that fd
might be -1, but even when it isn't -1 you shouldn't access fd
anymore.
void Passenger::EventedClient::notifyReads | ( | bool | enable | ) | [inline] |
Sets whether you're interested in read events.
This will start or stop the input readiness watcher appropriately according to the current state.
If the client connection is already being closed or has already been closed then this method does nothing.
size_t Passenger::EventedClient::pendingWrites | ( | ) | const [inline] |
Returns the number of bytes that are scheduled to be sent to the client at a later time.
bool Passenger::EventedClient::readWatcherActive | ( | ) | const [inline] |
Used by unit tests.
void Passenger::EventedClient::setOutboxLimit | ( | unsigned int | size | ) | [inline] |
Sets a limit on the client outbox.
The outbox is where data is stored that could not be immediately sent to the client, e.g. because of network congestion. Whenver the outbox's size grows past this limit, EventedClient will enter a state in which it will stop listening for read events and instead concentrate on sending out all pending data.
Setting this to 0 means that the outbox has an unlimited size. Please note however that this also means that the outbox's memory could grow unbounded if the client is too slow at receiving data.
The default value is some non-zero value.
If the client connection is already being closed or has already been closed then this method does nothing.
void Passenger::EventedClient::unref | ( | ) | [inline] |
Decrease reference count.
Upon reaching 0, this EventedClient object will be destroyed.
void Passenger::EventedClient::write | ( | const StaticString | data[], | |
unsigned int | count | |||
) | [inline] |
Sends data to this client.
This method will try to send the data immediately (in which no intermediate copies of the data will be made), but if the client is not yet ready to receive data (e.g. because of network congestion) then the data will be buffered and scheduled for sending later.
If an I/O error was encountered then the client connection will be closed by calling disconnect(true)
. This means this method could potentially call the onDisconnect
callback.
If the client connection is already being closed or has already been closed then this method does nothing.
The onPendingDataFlushed
callback will be called after this data and whatever existing pending data have been written out. That may either be immediately or after a short period of of time.
The client's file descriptor.
Could be -1: see ioAllowed()
.
Called when the client is disconnected.
This happens either immediately when disconnect()
is called, or a short amount of time later. See the documentation for that function for details.
Please note that destroying an EventedClient object does *not* cause this callback to be called.
Called after all pending outgoing data have been written out.
If write()
can be completed immediately without scheduling data for later, then write()
will call this callback immediately after writing.
Callback Passenger::EventedClient::onReadable |
Called when the file descriptor becomes readable and read notifications are enabled (see notifyRead()
).
When there's too much pending outgoing data, readability notifications are temporarily disabled; see write()
for details.
EventedClient doesn't do anything with this.
Set it to whatever you want.