- fix binary search args order - fix missing pollcat_dump() if POLLCAT_DEBUG=0 - safety check on null fp if stderr/stdout closed
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 internalpollfdarray, or change the events value on an existing entryvoid pollcat_fd_remove()- Remove an FD from the internalpollfdarrayshort int pollcat_events_get()- Get the events field for an FDvoid pollcat_events_set()- Set the events field for an FDshort int pollcat_revents()- Get the revents field for an FD, afterpoll()pollcat_time_reduce()- Reduce the current timeout if time is shorterint pollcat_poll()- Callpoll()on the internalpollfdarray and current timeoutextern pollcat_assert_f pollcat_assert_func- Optional user-supplied function to handle fatal errors; if unset a message will be printed to stderr andabort()called to terminate the processextern int pollcat_time_base- The base timeout in milliseconds forpoll()- the current timeout is reset to this after each wrappedpoll()call. The default is set at compile time with the symbolPOLLCAT_TIME_BASEextern int pollcat_time_minimum- The minimum timeout in milliseconds forpoll()- the default is set at compile time with the symbolPOLLCAT_TIME_MINIMUMextern size_t pollcat_size_initial- The initial size of the internalpollfdarray. The default is set at compile time with the symbolPOLLCAT_SIZE_INITIALextern size_t pollcat_size_increment- The incremental size to grow the internalpollfdarray by when necessary. The default is set at compile time with the symbolPOLLCAT_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 argumentvoid pollcat_timer_detach()- Detach a timer from the active listvoid pollcat_timer_reduce_timeout()- Calculate the deadline to the next timer due, and reduce thepoll()timeout to match, if less than the current timeoutvoid pollcat_timer_dispatch()- Execute timers which are dueextern int pollcat_timer_dispatch_max- Sets the maximum number of timers executed per call topollcat_timer_dispatch()extern pollcat_time_t pollcat_timer_dispatch_thresh- Sets a "grace" time for delayed timerstypedef 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 functionsstruct 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 listvoid pollcat_iter_remove()- Remove a Pollcat object from the iterator listvoid pollcat_iter_reset()- Reset the cursor on the iterator liststruct pollcat *pollcat_iter_next()- Return the next Pollcat object on the listint pollcat_loop()- Service active timers and Pollcat objects; returns true as long as main loop should continuevoid pollcat_loop_exit()- Sets a flag sopollcat_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.