/* -*-c-*-
*
- * $Id: sel.h,v 1.3 1999/05/17 20:36:36 mdw Exp $
+ * $Id: sel.h,v 1.7 1999/12/10 23:42:04 mdw Exp $
*
* I/O multiplexing support
*
/*----- Revision history --------------------------------------------------*
*
* $Log: sel.h,v $
+ * Revision 1.7 1999/12/10 23:42:04 mdw
+ * Change header file guard names.
+ *
+ * Revision 1.6 1999/08/31 17:42:22 mdw
+ * New function `sel_force' to force a descriptor to be `selected'.
+ *
+ * Revision 1.5 1999/08/19 18:30:26 mdw
+ * Implement hooks for foreign select-using systems (currently not well
+ * tested).
+ *
+ * Revision 1.4 1999/05/22 13:39:15 mdw
+ * Change spelling of `multiplexor'. ;-)
+ *
* Revision 1.3 1999/05/17 20:36:36 mdw
* Make the selector type symbols an enumeration rather than a bunch of
* #defines.
*
*/
-#ifndef SEL_H
-#define SEL_H
+#ifndef MLIB_SEL_H
+#define MLIB_SEL_H
#ifdef __cplusplus
extern "C" {
/*----- Data structures ---------------------------------------------------*/
+/* --- A multiplexor --- *
+ *
+ * The files are sorted in reverse order of file descriptor number; the
+ * timers are in normal order of occurrence. Thus, the interesting one
+ * is always at the front of the list.
+ */
+
+enum {
+ SEL_READ, /* File is ready to read */
+ SEL_WRITE, /* File is ready to write */
+ SEL_EXC, /* Something odd has happened */
+ SEL_MODES /* Number of modes available */
+};
+
+typedef struct sel_state {
+ struct sel_file *files[SEL_MODES]; /* Lists of interesting files */
+ struct sel_timer *timers; /* List of timers */
+ struct sel_hook *hooks; /* List of hook functions applied */
+ fd_set fd[SEL_MODES]; /* Quick reference table for files */
+ struct sel_args *args; /* Pointer to arguments */
+} sel_state;
+
/* --- Listening for a file --- */
typedef struct sel_file {
- struct sel_file *next;
- struct sel_file *prev;
- struct sel_state *s;
- int fd;
- unsigned mode;
- void (*func)(int /*fd*/, unsigned /*mode*/, void */*p*/);
- void *p;
+ struct sel_file *next; /* Next file in the list */
+ struct sel_file *prev; /* Previous file in the list */
+ struct sel_state *s; /* Pointer to select multiplexor */
+ int fd; /* File descriptor */
+ unsigned mode; /* Interesting event for file */
+ void (*func)(int /*fd*/, unsigned /*mode*/, void */*p*/); /* Handler */
+ void *p; /* Argument for the handler */
} sel_file;
-enum {
- SEL_READ,
- SEL_WRITE,
- SEL_EXC,
- SEL_MODES
-};
-
/* --- Waiting for a timeout --- */
typedef struct sel_timer {
- struct sel_timer *next;
- struct sel_timer *prev;
- struct timeval tv;
- void (*func)(struct timeval *tv, void *p);
- void *p;
+ struct sel_timer *next; /* Next timer in the list */
+ struct sel_timer *prev; /* Previous timer in the list */
+ struct timeval tv; /* Real time when timer should go */
+ void (*func)(struct timeval */*tv*/, void */*p*/); /* Handler function */
+ void *p; /* Argument for the handler */
} sel_timer;
-/* --- A multiplexer --- *
+/* --- A select argument block --- */
+
+typedef struct sel_args {
+ int maxfd; /* Highest-numbered file */
+ fd_set fd[SEL_MODES]; /* Bit flags for all the files */
+ struct timeval tv, *tvp; /* Time to return */
+ struct timeval now; /* Current time */
+} sel_args;
+
+/* --- A selector hook --- *
*
- * The files are sorted in reverse order of file descriptor number; the
- * timers are in normal order of occurrence. Thus, the interesting one
- * is always at the front of the list.
+ * The hooks are called (in arbitrary order) on each select.
*/
-typedef struct sel_state {
- struct sel_file *files;
- struct sel_timer *timers;
- fd_set fd[SEL_MODES];
- struct timeval tv;
-} sel_state;
+typedef void (*sel_hookfn)(sel_state */*s*/,
+ sel_args */*a*/,
+ void */*p*/);
+
+typedef struct sel_hook {
+ struct sel_hook *next; /* Next hook in the list */
+ struct sel_hook *prev; /* Previous hook in the list */
+ sel_hookfn before, after; /* Hook functions */
+ void *p; /* Argument for the hook functions */
+} sel_hook;
/*----- Functions provided ------------------------------------------------*/
extern void sel_rmfile(sel_file */*f*/);
+/* --- @sel_force@ --- *
+ *
+ * Arguments: @sel_file *f@ = pointer to file selector
+ *
+ * Returns: ---
+ *
+ * Use: Forces a file selector to be considered ready. This is only
+ * useful during a call to @sel_select@. Of particular use is
+ * forcing a write selector when there's something interesting
+ * ready for it.
+ */
+
+extern void sel_force(sel_file */*f*/);
+
/* --- @sel_addtimer@ --- *
*
* Arguments: @sel_state *s@ = pointer to a state block
* @sel_timer *t@ = pointer to a timer block
* @struct timeval *tv@ = pointer to time to activate
- * @void (*func)(struct timeval *tv, void *p)@ = handler
* @void *p@ = argument for handler function
*
* Returns: ---
extern void sel_rmtimer(sel_timer */*t*/);
+/* --- @sel_addhook@ --- *
+ *
+ * Arguments: @sel_state *s@ = pointer to state block
+ * @sel_hook *h@ = pointer to hook block
+ * @sel_hookfn before, after@ = hook functions
+ * @void *p@ = pointer argument to pass to hook functions
+ *
+ * Returns: ---
+ *
+ * Use: Registers hook functions to be called on each select call.
+ */
+
+extern void sel_addhook(sel_state */*s*/, sel_hook */*h*/,
+ sel_hookfn /*before*/, sel_hookfn /*after*/,
+ void */*p*/);
+
+/* --- @sel_rmhook@ --- *
+ *
+ * Arguments: @sel_hook *h@ = pointer to hook block
+ *
+ * Returns: ---
+ *
+ * Use: Removes hook functions.
+ */
+
+extern void sel_rmhook(sel_hook */*h*/);
+
+/* --- @sel_fdmerge@ --- *
+ *
+ * Arguments: @fd_set *dest@ = destination FD set
+ * @fd_set *fd@ = pointer to set to merge
+ * @int maxfd@ = highest numbered descriptor in @fd@ + 1
+ *
+ * Returns: Actual highest numbered descriptor.
+ *
+ * Use: Merges file descriptor sets, and returns an accurate @maxfd@
+ * value.
+ */
+
+extern int sel_fdmerge(fd_set */*dest*/, fd_set */*fd*/, int /*maxfd*/);
+
/* --- @sel_select@ --- *
*
* Arguments: @sel_state *s@ = pointer to state block