112 lines
5.7 KiB
Markdown
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.
|
|
|
|
|