summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2012-05-19 17:58:08 +0200
committerDavid Herrmann <dh.herrmann@googlemail.com>2012-05-19 17:58:08 +0200
commit00ff46b701213da02745f756db0ab9bae85634da (patch)
tree452d577b0325b944f8d426c6ba961ebd3d8b896c
parent0b8da0ce5027127e25b0c72e70201a4fcb92a09b (diff)
eloop: add initial gtk-doc comments
Add gtk-doc compatible comments to most of the functions in eloop.c. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
-rw-r--r--src/eloop.c358
1 files changed, 307 insertions, 51 deletions
diff --git a/src/eloop.c b/src/eloop.c
index 691ede0..e3210f8 100644
--- a/src/eloop.c
+++ b/src/eloop.c
@@ -24,11 +24,27 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/*
- * Event Loop
- * This provides a basic event loop similar to those provided by glib etc.
- * It uses linux specific features like signalfd so it may not be easy to port
- * it to other platforms.
+/**
+ * SECTION:eloop
+ * @short_description: Event loop
+ * @include: eloop.h
+ *
+ * The event loop allows to register event sources and poll them for events.
+ * When an event occurs, the user-supplied callback is called.
+ *
+ * The event-loop allows the callbacks to modify _any_ data they want. They can
+ * remove themself or other sources from the event loop even in a callback.
+ *
+ * Sources can be one of:
+ * - File descriptors: An fd that is watched for readable/writeable events
+ * - Timers: An event that occurs after a relative timeout
+ * - Counters: An event that occurs when the counter is non-zero
+ * - Signals: An event that occurs when a signal is caught
+ * - Idle: An event that occurs when nothing else is done
+ * - Eloop: An event loop itself can be a source of another event loop
+ *
+ * A source can be registered for a single event-loop only! You cannot add it to
+ * multiple event loops simultaneously.
*/
#include <errno.h>
@@ -51,20 +67,21 @@
#define LOG_SUBSYSTEM "eloop"
-/*
- * Event Loop
+/**
+ * ev_eloop:
+ * @efd: The epoll file descriptor.
+ * @ref: refcnt of this object
+ * @fd: Event source around \efd so you can nest event loops
+ * @cnt: Counter source used for idle events
+ * @sig_list: Shared signal sources
+ * @idlers: List of idle sources
+ * @cur_fds: Current dispatch array of fds
+ * @cur_fds_cnt: size of \cur_fds
+ * @exit: true if we should exit the main loop
+ *
* An event loop is an object where you can register event sources. If you then
* sleep on the event loop, you will be woken up if a single event source is
* firing up. An event loop itself is an event source so you can nest them.
- * \efd: The epoll file descriptor.
- * \ref: refcnt of this object
- * \fd: Event source around \efd so you can nest event loops
- * \cnt: Counter source used for idle events
- * \sig_list: Shared signal sources
- * \idlers: List of idle sources
- * \cur_fds: Current dispatch array of fds
- * \cur_fds_cnt: size of \cur_fds
- * \exit: true if we should exit the main loop
*/
struct ev_eloop {
int efd;
@@ -81,16 +98,18 @@ struct ev_eloop {
bool exit;
};
-/*
- * FD sources
- * File descriptors are used internally for all kinds of sources.
- * \ref: refcnt for object
- * \fd: the actual file desciptor
- * \mask: the event mask for this fd (EV_READABLE, EV_WRITABLE, ...)
- * \cb: the user callback
- * \data: the user data
- * \enabled: true if the object is currently enabled
- * \loop: NULL or pointer to eloop if bound
+/**
+ * ev_fd:
+ * @ref: refcnt for object
+ * @fd: the actual file desciptor
+ * @mask: the event mask for this fd (EV_READABLE, EV_WRITABLE, ...)
+ * @cb: the user callback
+ * @data: the user data
+ * @enabled: true if the object is currently enabled
+ * @loop: NULL or pointer to eloop if bound
+ *
+ * File descriptors are the most mosic event source. Internally, they are used
+ * to implement all other kinds of event sources.
*/
struct ev_fd {
unsigned long ref;
@@ -103,14 +122,15 @@ struct ev_fd {
struct ev_eloop *loop;
};
-/*
- * Timer sources
+/**
+ * ev_timer:
+ * @ref: refcnt of this object
+ * @cb: user callback
+ * @data: user data
+ * @fd: the timerfd file desciptor
+ * @efd: fd-source for @fd
+ *
* Based on timerfd this allows firing events based on relative timeouts.
- * \ref: refcnt of this object
- * \cb: user callback
- * \data: user data
- * \fd: the timerfd file desciptor
- * \efd: fd-source for \fd
*/
struct ev_timer {
unsigned long ref;
@@ -121,15 +141,16 @@ struct ev_timer {
struct ev_fd *efd;
};
-/*
- * Counter Sources
+/**
+ * ev_counter:
+ * @ref: refcnt of counter object
+ * @cb: user callback
+ * @data: user data
+ * @fd: eventfd file desciptor
+ * @efd: fd-source for @fd
+ *
* Counter sources fire if they are non-zero. They are based on the eventfd
* syscall in linux.
- * \ref: refcnt of counter object
- * \cb: user callback
- * \data: user data
- * \fd: eventfd file desciptor
- * \efd: fd-source for \fd
*/
struct ev_counter {
unsigned long ref;
@@ -140,14 +161,15 @@ struct ev_counter {
struct ev_fd *efd;
};
-/*
- * Shared Signal Sources
+/**
+ * ev_signal_shared:
+ * @list: list integration into ev_eloop object
+ * @fd: the signalfd file desciptor for this signal
+ * @signum: the actual signal number
+ * @hook: list of registered user callbacks for this signal
+ *
* A shared signal allows multiple listeners for the same signal. All listeners
* are called if the signal is catched.
- * \list: list integration into ev_eloop object
- * \fd: the signalfd file desciptor for this signal
- * \signum: the actual signal number
- * \hook: list of registered user callbacks for this signal
*/
struct ev_signal_shared {
struct kmscon_dlist list;
@@ -157,7 +179,7 @@ struct ev_signal_shared {
struct kmscon_hook *hook;
};
-/*
+/**
* Shared signals
* signalfd allows us to conveniently listen for incoming signals. However, if
* multiple signalfds are registered for the same signal, then only one of them
@@ -223,6 +245,18 @@ static void shared_signal_cb(struct ev_fd *fd, int mask, void *data)
}
}
+/**
+ * signal_new:
+ * @out: Shared signal storage where the new object is stored
+ * @loop: The event loop where this shared signal is registered
+ * @signum: Signal number that this shared signal is for
+ *
+ * This creates a new shared signal and links it into the list of shared signals
+ * in @loop. It automatically adds @signum to the signal mask of the current
+ * thread so the signal is blocked.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
static int signal_new(struct ev_signal_shared **out, struct ev_eloop *loop,
int signum)
{
@@ -272,6 +306,15 @@ err_free:
return ret;
}
+/**
+ * signal_free:
+ * @sig: The shared signal to be freed
+ *
+ * This unlinks the given shared signal from the event-loop where it was
+ * registered and destroys it. This does _not_ unblock the signal number that it
+ * was associated to. If you want this, you need to do this manually with
+ * pthread_sigmask().
+ */
static void signal_free(struct ev_signal_shared *sig)
{
int fd;
@@ -347,6 +390,15 @@ static void eloop_cnt_event(struct ev_counter *cnt, uint64_t num, void *data)
}
}
+/**
+ * ev_eloop_new:
+ * @out: Storage for the result
+ *
+ * This creates a new event-loop with ref-count 1. The new event loop is stored
+ * in @out and has no registered events.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_new(struct ev_eloop **out)
{
struct ev_eloop *loop;
@@ -406,6 +458,12 @@ err_free:
return ret;
}
+/**
+ * ev_eloop_ref:
+ * @loop: Event loop to be modified
+ *
+ * This increases the ref-count of @loop by 1.
+ */
void ev_eloop_ref(struct ev_eloop *loop)
{
if (!loop)
@@ -414,6 +472,15 @@ void ev_eloop_ref(struct ev_eloop *loop)
++loop->ref;
}
+/**
+ * ev_eloop_unref:
+ * @loop: Event loop to be modified
+ *
+ * This decreases the ref-count of @loop by 1. If it drops to zero, the event
+ * loop is destroyed. Note that every registered event source takes a ref-count
+ * of the event loop so this ref-count will never drop to zero while there is an
+ * registered event source.
+ */
void ev_eloop_unref(struct ev_eloop *loop)
{
struct ev_signal_shared *sig;
@@ -438,6 +505,14 @@ void ev_eloop_unref(struct ev_eloop *loop)
free(loop);
}
+/**
+ * ev_eloop_flush_fd:
+ * @loop: The event loop where @fd is registered
+ * @fd: The fd to be flushed
+ *
+ * If @loop is currently dispatching events, this will remove all pending events
+ * of @fd from the current event-list.
+ */
void ev_eloop_flush_fd(struct ev_eloop *loop, struct ev_fd *fd)
{
int i;
@@ -453,6 +528,24 @@ void ev_eloop_flush_fd(struct ev_eloop *loop, struct ev_fd *fd)
}
}
+/**
+ * ev_eloop_dispatch:
+ * @loop: Event loop to be dispatched
+ * @timeout: Timeout in milliseconds
+ *
+ * This listens on @loop for incoming events and handles all events that
+ * occured. This waits at most @timeout milliseconds until returning. If
+ * @timeout is -1, this waits until the first event arrives. If @timeout is 0,
+ * then this returns directly if no event is currently pending.
+ *
+ * This performs only a single dispatch round. That is, if all sources where
+ * checked for events and there are no more pending events, this will return. If
+ * it handled events and the timeout has not elapsed, this will still return.
+ *
+ * If ev_eloop_exit() was called on @loop, then this will return immediately.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_dispatch(struct ev_eloop *loop, int timeout)
{
struct epoll_event *ep;
@@ -517,10 +610,21 @@ int ev_eloop_dispatch(struct ev_eloop *loop, int timeout)
return 0;
}
-/* ev_eloop_dispatch() performs one idle-roundtrip. This function performs as
- * many idle-roundtrips as needed to run \timeout milliseconds.
- * If \timeout is 0, this is equal to ev_eloop_dispath(), if \timeout is <0,
- * this runs until \loop->exit becomes true.
+/**
+ * ev_eloop_run:
+ * @loop: The event loop to be run
+ * @timeout: Timeout for this operation
+ *
+ * This is similar to ev_eloop_dispatch() but runs _exactly_ for @timeout
+ * milliseconds. It calls ev_eloop_dispatch() as often as it can until the
+ * timeout has elapsed. If @timeout is -1 this will run until you call
+ * ev_eloop_exit(). If @timeout is 0 this is equal to calling
+ * ev_eloop_dispatch() with a timeout of 0.
+ *
+ * Calling ev_eloop_exit() will always interrupt this function and make it
+ * return.
+ *
+ * Returns: 0 on success, otherwise a negative error code
*/
int ev_eloop_run(struct ev_eloop *loop, int timeout)
{
@@ -560,6 +664,12 @@ int ev_eloop_run(struct ev_eloop *loop, int timeout)
return 0;
}
+/**
+ * ev_eloop_exit:
+ * @loop: Event loop that should exit
+ *
+ * This makes a call to ev_eloop_run() stop.
+ */
void ev_eloop_exit(struct ev_eloop *loop)
{
if (!loop)
@@ -572,6 +682,16 @@ void ev_eloop_exit(struct ev_eloop *loop)
ev_eloop_exit(loop->fd->loop);
}
+/**
+ * ev_eloop_new_eloop:
+ * @loop: The parent event-loop where the new event loop is registered
+ * @out: Storage for new event loop
+ *
+ * This creates a new event loop and directly registeres it as event source on
+ * the parent event loop \loop.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_new_eloop(struct ev_eloop *loop, struct ev_eloop **out)
{
struct ev_eloop *el;
@@ -595,6 +715,16 @@ int ev_eloop_new_eloop(struct ev_eloop *loop, struct ev_eloop **out)
return 0;
}
+/**
+ * ev_eloop_add_eloop:
+ * @loop: Parent event loop
+ * @add: The event loop that is registered as event source on @loop
+ *
+ * This registers the existing event loop @add as event source on the parent
+ * event loop @loop.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_add_eloop(struct ev_eloop *loop, struct ev_eloop *add)
{
int ret;
@@ -623,6 +753,14 @@ int ev_eloop_add_eloop(struct ev_eloop *loop, struct ev_eloop *add)
return 0;
}
+/**
+ * ev_eloop_rm_eloop:
+ * @rm: Event loop to be unregistered from its parent
+ *
+ * This unregisters the event loop @rm as event source from its parent. If this
+ * event loop was not registered on any other event loop, then this call does
+ * nothing.
+ */
void ev_eloop_rm_eloop(struct ev_eloop *rm)
{
if (!rm || !rm->fd->loop)
@@ -642,6 +780,22 @@ void ev_eloop_rm_eloop(struct ev_eloop *rm)
* called until you enable it again.
*/
+/**
+ * ev_fd_new:
+ * @out: Storage for result
+ * @rfd: The actual file desciptor
+ * @mask: Bitmask of %EV_READABLE and %EV_WRITeABLE flags
+ * @cb: User callback
+ * @data: User data
+ *
+ * This creates a new file desciptor source that is watched for the events set
+ * in @mask. @rfd is the system filedescriptor. The resulting object is stored
+ * in @out. @cb and @data are the user callback and the user-supplied data that
+ * is passed to the callback on events.
+ * The FD is automatically watched for EV_HUP and EV_ERR events, too.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_fd_new(struct ev_fd **out, int rfd, int mask, ev_fd_cb cb, void *data)
{
struct ev_fd *fd;
@@ -665,6 +819,12 @@ int ev_fd_new(struct ev_fd **out, int rfd, int mask, ev_fd_cb cb, void *data)
return 0;
}
+/**
+ * ev_fd_ref:
+ * @fd: FD object
+ *
+ * Increases the ref-count of @fd by 1.
+ */
void ev_fd_ref(struct ev_fd *fd)
{
if (!fd)
@@ -673,6 +833,13 @@ void ev_fd_ref(struct ev_fd *fd)
++fd->ref;
}
+/**
+ * ev_fd_unref:
+ * @fd: FD object
+ *
+ * Decreases the ref-count of @fd by 1. Destroys the object if the ref-count
+ * drops to zero.
+ */
void ev_fd_unref(struct ev_fd *fd)
{
if (!fd || !fd->ref || --fd->ref)
@@ -744,6 +911,15 @@ static int fd_epoll_update(struct ev_fd *fd)
return 0;
}
+/**
+ * ev_fd_enable:
+ * @fd: FD object
+ *
+ * This enables @fd. By default every fd object is enabled. If you disabled it
+ * you can re-enable it with this call.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_fd_enable(struct ev_fd *fd)
{
int ret;
@@ -761,6 +937,13 @@ int ev_fd_enable(struct ev_fd *fd)
return 0;
}
+/**
+ * ev_fd_disable:
+ * @fd: FD object
+ *
+ * Disables @fd. That means, no more events are handled for @fd until you
+ * re-enable it with ev_fd_enable().
+ */
void ev_fd_disable(struct ev_fd *fd)
{
if (!fd || !fd->enabled)
@@ -770,16 +953,42 @@ void ev_fd_disable(struct ev_fd *fd)
fd_epoll_remove(fd);
}
+/**
+ * ev_fd_is_enabled:
+ * @fd: FD object
+ *
+ * Returns whether the fd object is enabled or disabled.
+ *
+ * Returns: true if @fd is enabled, otherwise false.
+ */
bool ev_fd_is_enabled(struct ev_fd *fd)
{
return fd && fd->enabled;
}
+/**
+ * ev_fd_is_bound:
+ * @fd: FD object
+ *
+ * Returns true if the fd object is bound to an event loop.
+ *
+ * Returns: true if @fd is bound, otherwise false
+ */
bool ev_fd_is_bound(struct ev_fd *fd)
{
return fd && fd->loop;
}
+/**
+ * ev_fd_set_cb_data:
+ * @fd: FD object
+ * @cb: New user callback
+ * @data: New user data
+ *
+ * This changes the user callback and user data that were set in ev_fd_new().
+ * Both can be set to NULL. If @cb is NULL, then the callback will not be called
+ * anymore.
+ */
void ev_fd_set_cb_data(struct ev_fd *fd, ev_fd_cb cb, void *data)
{
if (!fd)
@@ -789,6 +998,15 @@ void ev_fd_set_cb_data(struct ev_fd *fd, ev_fd_cb cb, void *data)
fd->data = data;
}
+/**
+ * ev_fd_update:
+ * @fd: FD object
+ * @mask: Bitmask of %EV_READABLE and %EV_WRITEABLE
+ *
+ * This resets the event mask of @fd to @mask.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_fd_update(struct ev_fd *fd, int mask)
{
int ret;
@@ -812,6 +1030,23 @@ int ev_fd_update(struct ev_fd *fd, int mask)
return 0;
}
+/**
+ * ev_eloop_new_fd:
+ * @loop: Event loop
+ * @out: Storage for result
+ * @rfd: File descriptor
+ * @mask: Bitmask of %EV_READABLE and %EV_WRITEABLE
+ * @cb: User callback
+ * @data: User data
+ *
+ * This creates a new fd object like ev_fd_new() and directly registers it in
+ * the event loop @loop. See ev_fd_new() and ev_eloop_add_fd() for more
+ * information.
+ * The ref-count of @out is 1 so you must call ev_eloop_rm_fd() to destroy the
+ * fd. You must not call ev_fd_unref() unless you called ev_fd_ref() before.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_new_fd(struct ev_eloop *loop, struct ev_fd **out, int rfd,
int mask, ev_fd_cb cb, void *data)
{
@@ -836,6 +1071,17 @@ int ev_eloop_new_fd(struct ev_eloop *loop, struct ev_fd **out, int rfd,
return 0;
}
+/**
+ * ev_eloop_add_fd:
+ * @loop: Event loop
+ * @fd: FD Object
+ *
+ * Registers @fd in the event loop @loop. This increases the ref-count of both
+ * @loop and @fd. From now on the user callback of @fd may get called during
+ * dispatching.
+ *
+ * Returns: 0 on success, otherwise negative error code
+ */
int ev_eloop_add_fd(struct ev_eloop *loop, struct ev_fd *fd)
{
int ret;
@@ -858,6 +1104,16 @@ int ev_eloop_add_fd(struct ev_eloop *loop, struct ev_fd *fd)
return 0;
}
+/**
+ * ev_eloop_rm_fd:
+ * @fd: FD object
+ *
+ * Removes the fd object @fd from its event loop. If you did not call
+ * ev_eloop_add_fd() before, this will do nothing.
+ * This decreases the refcount of @fd and the event loop by 1.
+ * It is safe to call this in any callback. This makes sure that the current
+ * dispatcher will not get confused or read invalid memory.
+ */
void ev_eloop_rm_fd(struct ev_fd *fd)
{
struct ev_eloop *loop;