#ifndef _POLLLOOP_H_7958f73d_ #define _POLLLOOP_H_7958f73d_ /* This file is in the public domain. */ /* * Main-loop package. This lets you install read and/or write handlers * for file descriptors and set up block functions which are called * when a poll() is about to block. * * There can be only one main loop using this package per program. * This is because it maintains private data structures in variables * of static storage duration (file-local to pollloop.c). Arguably * these should be collected into a state structure (eg, returned by * init_polling), but so far it hasn't seemed worth doing. * * Note that IDs returned by add_poll_fd() and add_block_fn() are in * separate namespaces; except that PL_NOID is the same for both, * there is no connection between them - fd poll ID 3 and block * function id 3 bear no more relation to one another than file * descriptor 3 and process ID 3 do in Unix. */ /* * Initalize the whole package. THis must be called before any of the * other functions. */ extern void init_polling(void); /* * Add a file descriptor. Args are * * add_poll_fd(fd,rtest,wtest,rd,wr,cookie) * * fd is of course the file descriptor to be added to the poll() pot. * rtest and wtest are called to test whether we want to find out * whether we can read or write, respectively, the descriptor; rd/wr * are called if rtest/wtest returned true and then poll indicated * readability/writability. The cookie is passed as the argument to * rtest, wtest, rd, and wr. * * A descriptor may be added to the pot more than once, but it is * usually not useful to do so more than twice (once for read and once * for write). * * Return value is an int handle, not equal to PL_NOID, which is an * idenfitier for this poll. */ extern int add_poll_fd(int, int (*)(void *), int (*)(void *), void (*)(void *), void (*)(void *), void *); /* * Add a block function. This is called whenever it looks as though a * poll() will probably block. This is suitable for doing tasks that * should take a back seat to handling I/O. * * Return value is BLOCK_NIL to mean "nothing for me to do at the * moment, go ahead and block or let someone else do soemthing", * BLOCK_LOOP to mean "things may have changed, go around the whole * loop again", or a nonnegative number which is a maximum number of * microseconds to block. * * Return value is an int handle, not equal to PL_NOID, which is an * idenfitier for this block function. */ extern int add_block_fn(int (*)(void *), void *); #define BLOCK_NIL (-1) #define BLOCK_LOOP (-2) /* * Undoes an add_poll_fd, given the ID returned by it. Once this call * is made, the ID handle goes invalid and may be reused by a future * call to add_poll_fd. * * Calling this with an invalid ID - one not currently corresponding to * a call to add_poll_id() - is a fatal bug, causing an abort(). */ extern void remove_poll_id(int); /* * Undoes an add_block_fn, given the ID returned by it. Once this call * is made, the ID handle goes invalid and may be reused by a future * call to add_block_fn. * * Calling this with an invalid ID - one not currently corresponding to * a call to add_block_fn() - is a fatal bug, causing an abort(). */ extern void remove_block_id(int); /* * The next three are the parts of the main loop. A vanilla main loop * will look like * * while (1) * { pre_poll(); * if (do_poll() < 0) * { ...check errno and handle any real error... * } * post_poll(); * } * * do_poll's return value is a return from poll(2), or, if some block * function returned BLOCK_LOOP, zero. These three functions * communicate via private variables; see this file's header comment * for a brief discussion of this choice. */ extern void pre_poll(void); extern int do_poll(void); extern void post_poll(void); /* * A special int value which will never be returned by add_poll_fd or * add_block_fn. Nothing else is promised about ID values; for * example, it is not promised that they will be clustered near zero, * or that they will be nonnegative. */ #define PL_NOID (-1) /* * Convenience test functions. (Pointers to) these may be passed as * the rtest and wtest arguments to add_poll_fd to indicate that we * always, or never, are interested in the relevant kind of I/O. * (These simply ignore their argument and return 1 (rwtest_always) or * 0 (rwtest_never).) */ extern int rwtest_always(void *); extern int rwtest_never(void *); #endif