Initial commit of Pollcat library

This commit is contained in:
2022-06-28 15:25:57 -07:00
commit bbd4625d43
26 changed files with 3534 additions and 0 deletions

31
include/pollcat.h Normal file
View File

@@ -0,0 +1,31 @@
/** Pollcat library include wrapper
*
* This file is part of the Pollcat Library.
* Copyright (C) 2022 Expatria Technologies Inc.
* Contact: Morgan Hughes <morgan@expatria.ca>
*
* The Pollcat Library is free software: you can redistribute it and/or modify it under
* the terms of the the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License and the GNU Lesser
* General Public License along with the Pollcat Library. If not, see
* https://www.gnu.org/licenses/
*
* vim:ts=4:noexpandtab
*/
#ifndef _INCLUDE_POLLCAT_H_
#define _INCLUDE_POLLCAT_H_
#include "pollcat/pollcat.h"
#include "pollcat/timer.h"
#include "pollcat/struct.h"
#endif /* _INCLUDE_POLLCAT_H_ */

133
include/pollcat/pollcat.h Normal file
View File

@@ -0,0 +1,133 @@
/** Wrapper structure for poll()
*
* This file is part of the Pollcat Library.
* Copyright (C) 2022 Expatria Technologies Inc.
* Contact: Morgan Hughes <morgan@expatria.ca>
*
* The Pollcat Library is free software: you can redistribute it and/or modify it under
* the terms of the the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License and the GNU Lesser
* General Public License along with the Pollcat Library. If not, see
* https://www.gnu.org/licenses/
*
* vim:ts=4:noexpandtab
*/
#ifndef _INCLUDE_POLLCAT_POLLCAT_H_
#define _INCLUDE_POLLCAT_POLLCAT_H_
#ifndef POLLCAT_TIME_BASE
#define POLLCAT_TIME_BASE 250
#endif
#ifndef POLLCAT_TIME_MINIMUM
#define POLLCAT_TIME_MINIMUM 5
#endif
#ifndef POLLCAT_SIZE_INITIAL
#define POLLCAT_SIZE_INITIAL 8
#endif
#ifndef POLLCAT_SIZE_INCREMENT
#define POLLCAT_SIZE_INCREMENT 8
#endif
#ifndef POLLCAT_DEBUG
#define POLLCAT_DEBUG 1
#endif
#include <stdlib.h>
#include <poll.h>
#if POLLCAT_DEBUG
#include <stdio.h>
#endif
/** Optional function to call on fatal error; if unset an assert()-style message will be
* printed on stderr and exit(1) called.
*/
typedef void (* pollcat_assert_f) (const char *file, int line, const char *mesg);
extern pollcat_assert_f pollcat_assert_func;
/** Base timeout for wrapped poll() calls in milliseconds; pollcat_time_reduce() may be
* called to reduce this on a per-loop basis to improve latency of things like timers.
* The default is POLLCAT_TIME_BASE.
*/
extern int pollcat_time_base;
/** Minimum timeout for wrapped poll() calls in milliseconds; pollcat_time_reduce() will
* not reduce the per-loop timeout below this value. The default is POLLCAT_TIME_MINIMUM.
*/
extern int pollcat_time_minimum;
/** Initial size of the pollfd array. The default is POLLCAT_SIZE_INITIAL.
*/
extern size_t pollcat_size_initial;
/** Incremental size of the pollfd array. The default is POLLCAT_SIZE_INCREMENT.
*/
extern size_t pollcat_size_increment;
/** Add an FD to the poll array and set the events requested
*
* \param fd File descriptor
* \param events Bitmap of events from poll.h, such as POLLIN
*/
void pollcat_fd_add (int fd, short int events);
/** Get request bits of an FD in the poll array
*
* \param fd File descriptor
*
* \return bitmap on success, <0 on error
*/
short int pollcat_events_get (int fd);
/** Set request bits on an FD in the poll array
*
* \param fd File descriptor
* \param events Bitmap of events from poll.h, such as POLLIN
*/
void pollcat_events_set (int fd, short int events);
/** Get result bits of an FD in the poll array
*
* \param fd File descriptor
*
* \return bitmap on success, 0 on error
*/
short int pollcat_revents (int fd);
/** Remove an FD from the poll array
*
* \param fd File descriptor
*/
void pollcat_fd_remove (int fd);
/** Reduce the current timeout
*
* \param time New timeout in milliseconds
*/
void pollcat_time_reduce (int time);
/** Wraps the system poll() command using the internal pollfd array and timeout
*
* \return as per poll(), <0 on error
*/
int pollcat_poll (void);
#if POLLCAT_DEBUG
/** Prints the pollfd array to a given file handle
*/
void pollcat_dump (FILE *fp);
#endif
#endif /* _INCLUDE_POLLCAT_POLLCAT_H_ */

103
include/pollcat/struct.h Normal file
View File

@@ -0,0 +1,103 @@
/** Registration struct, iterators, and main-loop convenience functions
*
* This file is part of the Pollcat Library.
* Copyright (C) 2022 Expatria Technologies Inc.
* Contact: Morgan Hughes <morgan@expatria.ca>
*
* The Pollcat Library is free software: you can redistribute it and/or modify it under
* the terms of the the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License and the GNU Lesser
* General Public License along with the Pollcat Library. If not, see
* https://www.gnu.org/licenses/
*
* vim:ts=4:noexpandtab
*/
#ifndef _INCLUDE_POLLCAT_STRUCT_H_
#define _INCLUDE_POLLCAT_STRUCT_H_
#include <stdint.h>
struct pollcat_ops;
/** Pollcat object structure */
struct pollcat
{
void *data;
const struct pollcat_ops *ops;
struct pollcat *next;
};
/** Timer callbacks type takes a single void pointer */
typedef void (* pollcat_service_f)(struct pollcat *);
/** Operations structure for a pollcat object */
struct pollcat_ops
{
/* Prepare function is called before poll(); it's a good place to do things like
* accept() incoming connections, or add new file descriptors. */
pollcat_service_f prepare;
/* Service function is called after poll(); it's the place to check revents for FDs
* and do the appropriate read/write options. */
pollcat_service_f service;
};
/** Add a pollcat object to the internal iterator list
*
* \param cat Pointer to pollcat object
*/
void pollcat_iter_add (struct pollcat *cat);
/** Remove pollcat object from the internal iterator list
*
* \param cat Pointer to pollcat object
*/
void pollcat_iter_remove (struct pollcat *cat);
/** Reset cursor for internal iterator list
*/
void pollcat_iter_reset (void);
/** Return next pollcat object in internal iterator list
*
* \return Pointer to next pollcat object in list, or NULL at end of list
*/
struct pollcat *pollcat_iter_next (void);
/** Loop wrapper function
*
* This should be called as the test in a while() loop in main. Internally it will:
* - check whether pollcat_loop_exit() has been called, and return 0 if so
* - call pollcat_timer_reduce_timeout() to improve timer latency
* - call ops.prepare() on each pollcat object in the internal iterator list
* - call pollcat_poll() and optionally save the return value in poll-ret
* - call pollcat_timer_dispatch() to dispatch any expired timers
* - call ops.service() on each pollcat object in the internal iterator list
* - return nonzero for next loop
*
* \param poll_ret Optional pointer to int for return value from poll() call
*
* \return nonzero if main loop should continue, 0 if it should break
*/
int pollcat_loop (int *poll_ret);
/** Cause pollcat_loop() to return 0 on its next call
*/
void pollcat_loop_exit (void);
#endif /* _INCLUDE_POLLCAT_STRUCT_H_ */

95
include/pollcat/timer.h Normal file
View File

@@ -0,0 +1,95 @@
/** Millisecond-resolution event timers
*
* This file is part of the Pollcat Library.
* Copyright (C) 2022 Expatria Technologies Inc.
* Contact: Morgan Hughes <morgan@expatria.ca>
*
* The Pollcat Library is free software: you can redistribute it and/or modify it under
* the terms of the the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License and the GNU Lesser
* General Public License along with the Pollcat Library. If not, see
* https://www.gnu.org/licenses/
*
* vim:ts=4:noexpandtab
*/
#ifndef _INCLUDE_POLLCAT_TIMER_H_
#define _INCLUDE_POLLCAT_TIMER_H_
#include <stdint.h>
/** Clocks type adjustable in size, units milliseconds for compatibility with poll() */
typedef uint64_t pollcat_time_t;
/** Grace period in milliseconds for late timers, set to 0 for exact match */
extern pollcat_time_t pollcat_timer_dispatch_thresh;
/** Maximum number of times to run the dispatch loop, set to -1 for no limit */
extern int pollcat_timer_dispatch_max;
/** Timer callbacks type takes a single void pointer */
typedef void (* pollcat_timer_f)(void *);
/** Timer struct; zero-fill to init */
struct pollcat_timer
{
pollcat_timer_f func;
pollcat_time_t due;
void *arg;
struct pollcat_timer *next;
struct pollcat_timer *prev;
};
/** Detach a timer from the active list
*
* \param timer Pointer to timer struct
*/
void pollcat_timer_detach (struct pollcat_timer *timer);
/** Attach or re-attach a timer to the active list
*
* \param timer Pointer to timer struct
* \param msec Delay in milliseconds
* \param func Callback function
* \param arg Argument to callback function
*/
void pollcat_timer_attach (struct pollcat_timer *timer,
pollcat_time_t msec,
pollcat_timer_f func,
void *arg);
/** Returns nonzero if timer is attached
*
* \param timer Pointer to timer struct
*
* \return >0 if timer is attached
*/
int pollcat_timer_is_attached (struct pollcat_timer *timer);
/** Reduce the poll() timeout
*
* This should be called each main loop before the pollcat_poll() call, so that a ready
* timer isn't delayed.
*/
void pollcat_timer_reduce_timeout (void);
/** Dispatch ready timers
*/
void pollcat_timer_dispatch (void);
#endif /* _INCLUDE_POLLCAT_TIMER_H_ */