# 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.