Files
libpollcat/README.md

112 lines
5.7 KiB
Markdown

# Pollcat Library
Pollcat is a lightweight library which wraps the `poll()` system call and makes it easy to
build nonblocking applications where cooperative scheduling is adequate and threads are
not warranted.
It provides an API for managing a list of `pollfd` structs, timeouts, and the `poll()`
system call; millisecond-resolution oneshot timers; an embeddable struct to anchor
pollable objects; and iterators and wrappers for a simple main loop.
Operations which can fail (ie due to memory allocation) return void to simplify user code;
instead a fatal error triggers a callback to a user-supplied handler, or an error message
and call to `abort()`.
The library is released under LGPL v3.
## Poll API
An internal sorted `pollfd` array is populated with functions which add, modify, and remove
FDs and event bitmasks; the returned events bitmask can be queried. An internal timeout
value is maintained and used inside the `poll()` call wrapper, it can be reduced by other
code to improve latency.
As with `poll()` timeouts are managed in milliseconds. Pollcat maintains an internal
minimum timeout, used by default by the wrapped `poll()` call. Interfaces using pollcat
for non-blocking plumbing may optionally reduce the current timeout per loop, so the
`poll()` call returns when appropriate.
This is used by the timer API to ensure the `poll()` returns at the correct idle time so
the pending timer(s) can be serviced.
* `void pollcat_fd_add()` - Add an FD to the internal `pollfd` array, or change the events
value on an existing entry
* `void pollcat_fd_remove()` - Remove an FD from the internal `pollfd` array
* `short int pollcat_events_get()` - Get the events field for an FD
* `void pollcat_events_set()` - Set the events field for an FD
* `short int pollcat_revents()` - Get the revents field for an FD, after `poll()`
* `pollcat_time_reduce()` - Reduce the current timeout if time is shorter
* `int pollcat_poll()` - Call `poll()` on the internal `pollfd` array and current
timeout
* `extern pollcat_assert_f pollcat_assert_func` - Optional user-supplied function to
handle fatal errors; if unset a message will be printed to stderr and `abort()` called
to terminate the process
* `extern int pollcat_time_base` - The base timeout in milliseconds for `poll()` - the
current timeout is reset to this after each wrapped `poll()` call. The default is set
at compile time with the symbol `POLLCAT_TIME_BASE`
* `extern int pollcat_time_minimum` - The minimum timeout in milliseconds for `poll()` -
the default is set at compile time with the symbol `POLLCAT_TIME_MINIMUM`
* `extern size_t pollcat_size_initial` - The initial size of the internal `pollfd` array.
The default is set at compile time with the symbol `POLLCAT_SIZE_INITIAL`
* `extern size_t pollcat_size_increment` - The incremental size to grow the internal
`pollfd` array by when necessary. The default is set at compile time with the symbol
`POLLCAT_SIZE_INCREMENT`
## Event Timers
A simple oneshot timer is provided for timed events; timers can be detached and
re-attached at any time. If using the convenience functions, the due time for the
`poll()` timeout is automatically reduced to the nearest timer.
If not using the `pollcat_loop()` function, the user should call the timer reduction
function before `poll()` and the dispatch function after.
* `void pollcat_timer_attach()` - Attach a timer to the active list, specifying timeout in
milliseconds, callback function, and argument
* `void pollcat_timer_detach()` - Detach a timer from the active list
* `void pollcat_timer_reduce_timeout()` - Calculate the deadline to the next timer due,
and reduce the `poll()` timeout to match, if less than the current timeout
* `void pollcat_timer_dispatch()` - Execute timers which are due
* `extern int pollcat_timer_dispatch_max` - Sets the maximum number of timers executed per
call to `pollcat_timer_dispatch()`
* `extern pollcat_time_t pollcat_timer_dispatch_thresh` - Sets a "grace" time for delayed
timers
* `typedef uint64_t pollcat_time_t` - Sets the timer type, tunable for system size
## Embeddable Struct and Convenience API
Pollcat implements a base struct with linked-list and operations struct pointers. This
can be embedded in other structs to make them easily plugged into a polling main loop.
The `pollcat_loop()` function will iterate through the list, calling the supplied
`prepare()` function before `poll()` and the supplied `service()` function after.
Pollcat objects can be added to an internal list with the `pollcat_iter_add()` function,
and the main-loop function `pollcat_loop()` will iterate through them, perform the
`poll()` call, and service timers.
* `struct pollcat` - Pollcat object structure, passed to the convenience API functions
* `struct pollcat_ops` - Operations structure, with function pointers supplied by the user
or objects which wrap a Pollcat object.
* `void pollcat_iter_add()` - Add a Pollcat object to the iterator list
* `void pollcat_iter_remove()` - Remove a Pollcat object from the iterator list
* `void pollcat_iter_reset()` - Reset the cursor on the iterator list
* `struct pollcat *pollcat_iter_next()` - Return the next Pollcat object on the list
* `int pollcat_loop()` - Service active timers and Pollcat objects; returns true as long
as main loop should continue
* `void pollcat_loop_exit()` - Sets a flag so `pollcat_loop()` will return false and main
loop will stop
## Example Application
An example application is provided which demonstrates use of the library. It provides a
simple terminal to a serial device, with a command mode triggered by Ctrl-A. A timer
shows a menu after 1 second. The only command implemented is to shut down, via the Q or X
keys, with or without Ctrl.