Morgan Hughes c7729ca9b6 Minor bugfixes after testing
- fix binary search args order
- fix missing pollcat_dump() if POLLCAT_DEBUG=0
- safety check on null fp if stderr/stdout closed
2022-07-25 13:28:16 -07:00
2022-07-07 12:00:58 -07:00
2022-07-25 13:28:16 -07:00
2022-07-07 12:00:58 -07:00
2022-07-07 12:00:58 -07:00
2022-07-07 12:00:58 -07:00
2022-07-07 12:00:58 -07:00
2022-07-07 12:00:58 -07:00

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.

Description
No description provided
Readme 126 KiB
Languages
C 89%
Makefile 8.6%
Verilog 2.4%