event loop implementation More...
Go to the source code of this file.
Typedefs | |
typedef typedefCGUL_BEGIN_C struct event_loop * | event_loop_t |
typedef void * | event_loop__timeout_t |
typedef void(* | event_loop__fd_ready_cb_t) (cgul_exception_t *cex, int fd, void *data) |
typedef void(* | event_loop__timeout_cb_t) (cgul_exception_t *cex, event_loop__timeout_t timeout, void *data) |
typedef void(* | event_loop__signal_cb_t) (cgul_exception_t *cex, int signal_number, void *data) |
Functions | |
event_loop_t | event_loop__get_instance (cgul_exception_t *cex) |
void | event_loop__put_instance () |
event_loop_t | event_loop__new (cgul_exception_t *cex) |
void | event_loop__delete (event_loop_t loop) |
void | event_loop__start (cgul_exception_t *cex, event_loop_t loop) |
void | event_loop__stop (cgul_exception_t *cex, event_loop_t loop) |
void | event_loop__add_signal_handler (cgul_exception_t *cex, event_loop_t loop, int signal_number, event_loop__signal_cb_t cb, void *cb_data) |
void | event_loop__remove_signal_handler (cgul_exception_t *cex, event_loop_t loop, int signal_number) |
event_loop__timeout_t | event_loop__add_timeout (cgul_exception_t *cex, event_loop_t loop, double period, event_loop__timeout_cb_t cb, void *cb_data) |
void | event_loop__remove_timeout (cgul_exception_t *cex, event_loop_t loop, event_loop__timeout_t timeout) |
void | event_loop__add_read_fd (cgul_exception_t *cex, event_loop_t loop, int fd, event_loop__fd_ready_cb_t cb, void *cb_data) |
void | event_loop__remove_read_fd (cgul_exception_t *cex, event_loop_t loop, int fd) |
void | event_loop__add_write_fd (cgul_exception_t *cex, event_loop_t loop, int fd, event_loop__fd_ready_cb_t cb, void *cb_data) |
void | event_loop__remove_write_fd (cgul_exception_t *cex, event_loop_t loop, int fd) |
void | event_loop__add_exception_fd (cgul_exception_t *cex, event_loop_t loop, int fd, event_loop__fd_ready_cb_t cb, void *cb_data) |
void | event_loop__remove_exception_fd (cgul_exception_t *cex, event_loop_t loop, int fd) |
This class implements an event loop. This class is probably only functional on unix-like operating systems. This is why it is not part of cgul.
NOTE: This class is not thread-safe. This is by design because you generally only call this class's methods from the same thread. If you need to call this class's methods from multiple threads, you'll need to add external locking.
NOTE: This class is re-entrant. This allows any callback to directly add or remove any callback including itself.
typedef typedefCGUL_BEGIN_C struct event_loop* event_loop_t |
Opaque pointer to a event_loop
instance.
typedef void* event_loop__timeout_t |
Opaque pointer to a timeout handle.
typedef void(* event_loop__fd_ready_cb_t) (cgul_exception_t *cex, int fd, void *data) |
File descriptor ready callback. Functions you write that match this prototype can be registered to be called when the file descriptor fd
is ready. The data
parameter is the usual client data. The cex
parameter is a pointer that can be used to throw a c-style exception. Any exception that escapes this callback will be caught by the main event loop and printed to standard error. If you do not like this behavior, you do not have to use cex
, or you can catch it inside your function.
[in,out] | cex | c-style exception |
[in] | fd | file descriptor |
[in] | data | client data |
typedef void(* event_loop__timeout_cb_t) (cgul_exception_t *cex, event_loop__timeout_t timeout, void *data) |
Timeout expired callback. Functions you write that match this prototype can be registered to be called when a timeout expires. The timeout
parameter is the same value returned by event_loop__add_timeout()
. It can be used to remove the timeout so that its callback will no longer be called. The data
parameter is the usual client data. The cex
parameter is a pointer that can be used to throw a c-style exception. Any exception that escapes this callback will be caught by the main event loop and printed to standard error. If you do not like this behavior, you do not have to use cex
, or you can catch it inside your function.
[in,out] | cex | c-style exception |
[in] | timeout | timeout handle |
[in] | data | client data |
typedef void(* event_loop__signal_cb_t) (cgul_exception_t *cex, int signal_number, void *data) |
Posix asynchronous signal caught callback. Functions you write that match this prototype can be registered to be called when a particular signal has been caught. The signal_number
is the signal number for the signal that was caught. The data
parameter is the usual client data. The cex
parameter is a pointer that can be used to throw a c-style exception. Any exception that escapes this callback will be caught by the main event loop and printed to standard error. If you do not like this behavior, you do not have to use cex
, or you can catch it inside your function.
[in,out] | cex | c-style exception |
[in] | signal_number | signal number for the signal that was caught |
[in] | data | client data |
event_loop_t event_loop__get_instance | ( | cgul_exception_t * | cex | ) |
Get the single instance of the event_loop
class. The single instance is created the first time this method is called. If the instance cannot be created, an exception is thrown.
event_loop__new()
which cannot handle Posix asynchronous signals. [in,out] | cex | c-style exception |
Referenced by event_loop_cxx::get_instance().
void event_loop__put_instance | ( | ) |
Put the single instance of the event_loop
class. The single instance is destroyed whenever this method is called. In general, it should only be called before exiting the application if it is called at all.
Referenced by event_loop_cxx::put_instance().
event_loop_t event_loop__new | ( | cgul_exception_t * | cex | ) |
Create a new, per-thread event_loop
object that handles file descriptor and timeout events but not Posix asynchronous signal events. The caller is responsible for freeing the object by calling event_loop_delete()
. If memory cannot be allocated, NULL
is returned, and an exception is thrown.
event_loop
object using this method; instead, use the singleton returned by event_loop__get_instance()
which has global visibility and can handle Posix asynchronous signals. [in,out] | cex | c-style exception |
event_loop
instance Referenced by event_loop_cxx::event_loop_cxx().
void event_loop__delete | ( | event_loop_t | loop | ) |
This method frees all internally allocated memory associated with loop
. Do not try to access loop
after calling this method.
event_loop__new()
. Do not call this method on the singleton returned by event_loop__get_instance()
; instead call event_loop__put_instance()
to properly delete the singleton. [in] | loop | event_loop instance |
Referenced by event_loop_cxx::set_obj(), and event_loop_cxx::~event_loop_cxx().
void event_loop__start | ( | cgul_exception_t * | cex, |
event_loop_t | loop | ||
) |
This method starts the main event loop which only returns when one of the callbacks registered with the event loop invokes event_loop__stop()
.
[in] | cex | c-style exception |
[in] | loop | event_loop instance |
Referenced by event_loop_cxx::start().
void event_loop__stop | ( | cgul_exception_t * | cex, |
event_loop_t | loop | ||
) |
Call this method from within an event callback or from a different thread in order to stop processing events. This will cause event_loop__start
to return to its caller. This method is thread-safe. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
Referenced by event_loop_cxx::stop().
void event_loop__add_signal_handler | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | signal_number, | ||
event_loop__signal_cb_t | cb, | ||
void * | cb_data | ||
) |
This method arranges for cb
to be called synchronously with cb_data
when a Posix asynchronous signal is caught. The big advantage of this is that cb
runs in the synchronous context of the event loop's thread instead of in the asynchronous context of a true signal handler. If cb
is NULL
, the signal is effectively ignored. If the signal cannot be registered, an exception is thrown.
You can change cb
and cb_data
for a particular signal by calling this method more than once, but only one signal handler can simultaneously be registered per signal.
As a convenience, the event_loop
class is re-entrant with respect to the event loop's single thread of execution. This means you can call any of the methods of this class even from callbacks registered with this class.
If an error occurs, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | signal_number | signal number |
[in] | cb | callback |
[in] | cb_data | callback data passed to cb |
Referenced by event_loop_cxx::add_signal_handler().
void event_loop__remove_signal_handler | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | signal_number | ||
) |
Remove the the signal handler for the signal signal_number
from the list of Posix asynchronous signals handled by the event loop. This causes the default system action for the signal to be restored. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | signal_number | signal number |
Referenced by event_loop_cxx::remove_signal_handler().
event_loop__timeout_t event_loop__add_timeout | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
double | period, | ||
event_loop__timeout_cb_t | cb, | ||
void * | cb_data | ||
) |
This method adds a timeout event that repeatedly schedules itself every period
seconds. Because period
is a double, timeouts with millisecond resolution can easily be scheduled. The only guarantee regarding when the timeout occurs is that it occurs at least period
seconds after it has been scheduled. If period
is less than zero, the timeout will not be registered.
The event_loop
class is re-entrant with respect to the event loop's single thread of execution making it possible to remove a timeout from cb
itself.
The value returned is the handle for the timeout. It uniquely identifies the timeout and must be passed into event_loop__remove_timeout()
in order to remove the timeout. If you plan on removing the callback from inside cb
, you do not need to keep a reference to the value that is returned as it is always passed into your callback.
If an error occurs, NULL
is returned, and an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | period | timeout period |
[in] | cb_data | callback data passed to cb |
[in] | cb | callback |
Referenced by event_loop_cxx::add_timeout().
void event_loop__remove_timeout | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
event_loop__timeout_t | timeout | ||
) |
This function removes timeouts registered with event_loop__add_timeout()
. After calling this function, timeout
is invalid. If an error occurs, an exception is thrown.
This method can throw an out-of-memory exception. This can happen when this method is called from any timeout callback because this causes this class to be re-entered which requires that the request to remove the timeout be added to a queue so it can be honored later when it is safe to do so.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | timeout | timeout handle |
Referenced by event_loop_cxx::remove_timeout().
void event_loop__add_read_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd, | ||
event_loop__fd_ready_cb_t | cb, | ||
void * | cb_data | ||
) |
This method adds fd
to the list of file descriptors the event loop monitors. The event loop will then call cb
with the client-supplied cb_data
pointer when fd
is ready to be read.
You can change cb
and cb_data
for a particular file descriptor by calling this method more than once, but only one "read" callback per file descriptor can simultaneously be registered.
As a convenience, the event_loop
class is re-entrant with respect to the event loop's single thread of execution. This means you can call any of the methods of this class even from callbacks registered with this class.
If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to monitor |
[in] | cb | callback |
[in] | cb_data | callback data passed to cb |
Referenced by event_loop_cxx::add_read_fd().
void event_loop__remove_read_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd | ||
) |
Remove fd
from the list of file descriptors the event loop monitors to see when they are ready to be read. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to remove |
Referenced by event_loop_cxx::remove_read_fd().
void event_loop__add_write_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd, | ||
event_loop__fd_ready_cb_t | cb, | ||
void * | cb_data | ||
) |
This method adds fd
to the list of file descriptors the event loop monitors. The event loop will then call cb
with the client-supplied cb_data
pointer when fd
is ready to be written.
You can change cb
and cb_data
for a particular file descriptor by calling this method more than once, but only one "write" callback per file descriptor can simultaneously be registered.
As a convenience, the event_loop
class is re-entrant with respect to the event loop's single thread of execution. This means you can call any of the methods of this class even from callbacks registered with this class.
If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to monitor |
[in] | cb | callback |
[in] | cb_data | callback data passed to cb |
Referenced by event_loop_cxx::add_write_fd().
void event_loop__remove_write_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd | ||
) |
Remove fd
from the list of file descriptors the event loop monitors to see when they are ready to be written. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to remove |
Referenced by event_loop_cxx::remove_write_fd().
void event_loop__add_exception_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd, | ||
event_loop__fd_ready_cb_t | cb, | ||
void * | cb_data | ||
) |
This method adds fd
to the list of file descriptors the event loop monitors. The event loop will then call cb
with the client-supplied cb_data
pointer when fd
has an exception.
You can change cb
and cb_data
for a particular file descriptor by calling this method more than once, but only one "exception" callback per file descriptor can simultaneously be registered.
As a convenience, the event_loop
class is re-entrant with respect to the event loop's single thread of execution. This means you can call any of the methods of this class even from callbacks registered with this class.
If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to monitor |
[in] | cb | callback |
[in] | cb_data | callback data passed to cb |
Referenced by event_loop_cxx::add_exception_fd().
void event_loop__remove_exception_fd | ( | cgul_exception_t * | cex, |
event_loop_t | loop, | ||
int | fd | ||
) |
Remove fd
from the list of file descriptors the event loop monitors to see when an exception occurs. If an error occurs, an exception is thrown.
[in,out] | cex | c-style exception |
[in] | loop | event_loop instance |
[in] | fd | file descriptor to remove |
Referenced by event_loop_cxx::remove_exception_fd().