#ifndef WH_AIO_H_adb0730f_ #define WH_AIO_H_adb0730f_ /* This file is in the public domain. */ /* * Values for the second parameter to aio_oq_queue_special. */ typedef enum { AIO_SPECIAL_WRITE = 1, AIO_SPECIAL_DROP, } AIO_SPECIAL_TYPE; /* * Values for the second parameter to special callbacks. */ typedef enum { AIO_SPECIAL_NORMAL = 1, AIO_SPECIAL_FLUSH, } AIO_SPECIAL_OP; /* * The structs behind AIO_OQ and AIO_PQ are user-visible, though they * are explicitly not a part of the interface, because the interface * design has them allocated by user code, to avoid another level of * indirection. This then leaves us with a version skew risk: user * code may be built with version N structs and the library is then * modified in a way that includes changing the struct; linking with * the new library then explodes. To deal with this, aio_[op]q_init * is a macro which includes a version number, so that the library can * tell which version of the include file (and thus struct) it's * dealing with. This also satisfies the desire that aio_[op]q_init * be the actual function behind the API call, so that debuggers can * set breakpoints on it and the like. * * The "version number" paradigm admittedly depends on a possibly * nonportable assumption, namely, that two structs each beginning * with an int can be pointer-punned between with the int being * accessible from either, accessing the same value. This is not * explicitly promised by C, but I think it may be implied, on systems * supporting separate compilation, by 6.5.2.3 #5, and the way struct * pointers have to work across compilation unit boundaries. */ typedef struct aio_oq AIO_OQ; typedef struct aio_oqe AIO_OQE; typedef struct aio_pq AIO_PQ; typedef struct aio_pqe AIO_PQE; typedef struct aio_pp AIO_PP; typedef struct aio_pqpp AIO_PQPP; typedef struct aio_loop AIO_LOOP; struct aio_oq { int aio_version; union { struct { unsigned int aio_len; AIO_OQE *aio_head; AIO_OQE **aio_tail; } aio_v1; } ; } ; struct aio_pq { int aio_version; union { struct { unsigned int aio_len; unsigned int aio_npri; AIO_PQPP *aio_perpri; int aio_inprogress; } aio_v1; } ; } ; extern void aio_poll_init(void); extern void aio_poll_reinit(void); extern int aio_add_poll(int, int (*)(void *), int (*)(void *), void (*)(void *), void (*)(void *), void *); extern int aio_add_block(int (*)(void *), void *); #define AIO_BLOCK_NIL (-1) #define AIO_BLOCK_LOOP (-2) extern void aio_remove_poll(int); extern void aio_remove_block(int); extern int aio_pre_poll(void); extern int aio_do_poll(void); extern void aio_post_poll(void); extern AIO_LOOP *aio_poll_init_of(void); extern void aio_poll_done_of(AIO_LOOP *); extern int aio_add_poll_of(AIO_LOOP *, int, int (*)(void *), int (*)(void *), void (*)(void *), void (*)(void *), void *); extern int aio_add_block_of(AIO_LOOP *, int (*)(void *), void *); extern void aio_remove_poll_of(AIO_LOOP *, int); extern void aio_remove_block_of(AIO_LOOP *, int); extern int aio_pre_poll_l_of(int, ...); extern int aio_do_poll_l_of(int, ...); extern int aio_post_poll_l_of(int, ...); extern int aio_pre_poll_v_of(int, AIO_LOOP **); extern int aio_do_poll_v_of(int, AIO_LOOP **); extern void aio_post_poll_v_of(int, AIO_LOOP **); extern void aio_event_loop(void); #define AIO_NOID (-1) #define AIO_ERR (-2) #define AIO_PL_NOID (-1) extern int aio_rwtest_always(void *); extern int aio_rwtest_never(void *); /* * Value passed as the length argument to the oq_queue_* functions to * mean "use strlen of the buffer argument". * * This could be -1 except that that's too likely to occur by accident. */ #define AIO_STRLEN (-12345) /* * Value passed to aio_pq_flush to flush all priorities. * * This could be -1 except that that's too likely to occur by accident. */ #define AIO_ALL_PRIO (-12346) extern void aio_oq_init(AIO_OQ *, int); #define aio_oq_init(x) (aio_oq_init)((x),1) extern int aio_oq_queue_point(AIO_OQ *, const void *, int); extern int aio_oq_queue_copy(AIO_OQ *, const void *, int); extern int aio_oq_queue_free(AIO_OQ *, void *, int); extern int aio_oq_queue_cb(AIO_OQ *, const void *, int, void (*)(void *), void *); extern int aio_oq_queue_printf(AIO_OQ *, const char *, ...) __attribute__((__format__(__printf__,2,3))); extern int aio_oq_queue_special(AIO_OQ *, AIO_SPECIAL_TYPE, void (*)(AIO_SPECIAL_OP, void *, int), void *, int); extern void aio_oq_set_special_typecb(AIO_OQ *, AIO_SPECIAL_TYPE (*)(void *, int)); extern int aio_oq_writev(AIO_OQ *, int, int); #define AIO_WRITEV_ERROR (-1) #define AIO_WRITEV_SPECIAL (-2) extern int aio_oq_dropdata(AIO_OQ *, int); extern int aio_oq_dropdata_cb(AIO_OQ *, int, void (*)(const void *, int, void *), void *); extern unsigned int aio_oq_qlen(AIO_OQ *); extern int aio_oq_headlen(AIO_OQ *); #define AIO_OQ_HL_EMPTY (-1) #define AIO_OQ_HL_SPECIAL (-2) extern int aio_oq_empty(AIO_OQ *); extern int aio_oq_nonempty(AIO_OQ *); extern void aio_oq_flush(AIO_OQ *); extern int aio_pq_init(AIO_PQ *, int, int); #define aio_pq_init(x,y) (aio_pq_init)((x),1,(y)) extern void aio_pq_deinit(AIO_PQ *); extern int aio_pq_queue_point(AIO_PQ *, int, const void *, int); extern int aio_pq_queue_copy(AIO_PQ *, int, const void *, int); extern int aio_pq_queue_free(AIO_PQ *, int, void *, int); extern int aio_pq_queue_cb(AIO_PQ *, int, void *, int, void (*)(void *), void *); extern int aio_pq_queue_printf(AIO_PQ *, int, const char *, ...) __attribute__((__format__(__printf__,3,4))); extern int aio_pq_boundary(AIO_PQ *, int); extern int aio_pq_writev_drop(AIO_PQ *, int, int); extern unsigned int aio_pq_qlen(AIO_PQ *); extern int aio_pq_empty(AIO_PQ *); extern int aio_pq_nonempty(AIO_PQ *); extern void aio_pq_flush(AIO_PQ *, int); #endif