ioloop.h revision 85b14555888acec410734a16561f2d79c626cad9
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen#ifndef IOLOOP_H
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define IOLOOP_H
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <sys/time.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <time.h>
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainenstruct io;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct timeout;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainenstruct ioloop;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstruct istream;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenenum io_condition {
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen IO_READ = 0x01,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen IO_WRITE = 0x02,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen /* IO_ERROR can be used to check when writable pipe's reader side
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen closes the pipe. For other uses IO_READ should work just as well. */
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen IO_ERROR = 0x04,
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen /* internal */
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen IO_NOTIFY = 0x08
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen};
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenenum io_notify_result {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Notify added successfully */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen IO_NOTIFY_ADDED,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* Specified file doesn't exist, can't wait on it */
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen IO_NOTIFY_NOTFOUND,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Can't add notify for specified file. Main reasons for this:
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen a) No notify support at all, b) Only directory notifies supported */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen IO_NOTIFY_NOSUPPORT
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentypedef void io_callback_t(void *context);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentypedef void timeout_callback_t(void *context);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentypedef void io_loop_time_moved_callback_t(time_t old_time, time_t new_time);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentypedef void io_switch_callback_t(struct ioloop *prev_ioloop);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Time when the I/O loop started calling handlers.
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen Can be used instead of time(NULL). */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenextern time_t ioloop_time;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenextern struct timeval ioloop_timeval;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenextern struct ioloop *current_ioloop;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen/* You can create different handlers for IO_READ and IO_WRITE. IO_READ and
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen IO_ERROR can't use different handlers (and there's no point anyway).
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen Don't try to add multiple handlers for the same type. It's not checked and
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen the behavior will be undefined. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct io *io_add(int fd, enum io_condition condition,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int source_linenum,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen io_callback_t *callback, void *context) ATTR_NULL(5);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen#define io_add(fd, condition, callback, context) \
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen io_add(fd, condition, __LINE__ + \
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen (io_callback_t *)callback, context)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenenum io_notify_result
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenio_add_notify(const char *path, io_callback_t *callback,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen void *context, struct io **io_r) ATTR_NULL(3);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen#define io_add_notify(path, callback, context, io_r) \
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen io_add_notify(path + \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (io_callback_t *)callback, context, io_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct io *io_add_istream(struct istream *input, unsigned int source_linenum,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen io_callback_t *callback, void *context) ATTR_NULL(3);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define io_add_istream(input, callback, context) \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen io_add_istream(input, __LINE__ + \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (io_callback_t *)callback, context)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Remove I/O handler, and set io pointer to NULL. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_remove(struct io **io);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Like io_remove(), but assume that the file descriptor is already closed.
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen With some backends this simply frees the memory. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_remove_closed(struct io **io);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Make sure the I/O callback is called by io_loop_run() even if there isn't
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen any input actually pending currently as seen by the OS. This may be useful
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if some of the input has already read into some internal buffer and the
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen caller wants to handle it the same way as if the fd itself had input. */
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid io_set_pending(struct io *io);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen/* Timeout handlers */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct timeout *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentimeout_add(unsigned int msecs, unsigned int source_linenum,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen timeout_callback_t *callback, void *context) ATTR_NULL(4);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define timeout_add(msecs, callback, context) \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen timeout_add(msecs, __LINE__ + \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))) + \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen COMPILE_ERROR_IF_TRUE(__builtin_constant_p(msecs) && \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (msecs > 0 && msecs < 1000)), \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (io_callback_t *)callback, context)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct timeout *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainentimeout_add_short(unsigned int msecs, unsigned int source_linenum,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen timeout_callback_t *callback, void *context) ATTR_NULL(4);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define timeout_add_short(msecs, callback, context) \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen timeout_add_short(msecs, __LINE__ + \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (io_callback_t *)callback, context)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen/* Remove timeout handler, and set timeout pointer to NULL. */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid timeout_remove(struct timeout **timeout);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen/* Reset timeout so it's next run after now+msecs. */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid timeout_reset(struct timeout *timeout);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen/* Refresh ioloop_time and ioloop_timeval variables. */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid io_loop_time_refresh(void);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid io_loop_run(struct ioloop *ioloop);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid io_loop_stop(struct ioloop *ioloop); /* safe to run in signal handler */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenbool io_loop_is_running(struct ioloop *ioloop);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* call these if you wish to run the iteration only once */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid io_loop_set_running(struct ioloop *ioloop);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainenvoid io_loop_handler_run(struct ioloop *ioloop);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct ioloop *io_loop_create(void);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Specify the maximum number of fds we're expecting to use. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_loop_set_max_fd_count(struct ioloop *ioloop, unsigned int max_fds);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Destroy I/O loop and set ioloop pointer to NULL. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_loop_destroy(struct ioloop **ioloop);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen/* If time moves backwards or jumps forwards call the callback. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid io_loop_set_time_moved_callback(struct ioloop *ioloop,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen io_loop_time_moved_callback_t *callback);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* Change the current_ioloop. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_loop_set_current(struct ioloop *ioloop);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen/* Call the callback whenever ioloop is changed. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_loop_add_switch_callback(io_switch_callback_t *callback);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid io_loop_remove_switch_callback(io_switch_callback_t *callback);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen/* This context is used for all further I/O and timeout callbacks that are
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen added until returning to ioloop. When a callback is called, this context is
6600c05e2ab38e9f662582b63c56b0c980a03748Timo Sirainen again activated. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenstruct ioloop_context *io_loop_context_new(struct ioloop *ioloop);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenvoid io_loop_context_ref(struct ioloop_context *ctx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenvoid io_loop_context_unref(struct ioloop_context **ctx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen/* Call the activate callback when this context is activated (I/O callback is
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen about to be called), and the deactivate callback when the context is
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen deactivated (I/O callback has returned). You can add multiple callbacks. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenvoid io_loop_context_add_callbacks(struct ioloop_context *ctx,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen io_callback_t *activate,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen io_callback_t *deactivate, void *context);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen#define io_loop_context_add_callbacks(ctx, activate, deactivate, context) \
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen io_loop_context_add_callbacks(ctx, 1 ? (io_callback_t *)activate : \
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen CALLBACK_TYPECHECK(activate, void (*)(typeof(context))) + \
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen CALLBACK_TYPECHECK(deactivate, void (*)(typeof(context))), \
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen (io_callback_t *)deactivate, context)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* Remove callbacks with the given callbacks and context. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid io_loop_context_remove_callbacks(struct ioloop_context *ctx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen io_callback_t *activate,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen io_callback_t *deactivate, void *context);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#define io_loop_context_remove_callbacks(ctx, activate, deactivate, context) \
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen io_loop_context_remove_callbacks(ctx, 1 ? (io_callback_t *)activate : \
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen CALLBACK_TYPECHECK(activate, void (*)(typeof(context))) + \
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen CALLBACK_TYPECHECK(deactivate, void (*)(typeof(context))), \
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (io_callback_t *)deactivate, context)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* Returns the current context set to ioloop. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstruct ioloop_context *io_loop_get_current_context(struct ioloop *ioloop);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen/* Move the given I/O into the current I/O loop if it's not already
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen there. New I/O is returned, while the old one is freed. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstruct io *io_loop_move_io(struct io **io);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen/* Like io_loop_move_io(), but for timeouts. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstruct timeout *io_loop_move_timeout(struct timeout **timeout);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen/* Returns TRUE if any IOs have been added to the ioloop. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenbool io_loop_have_ios(struct ioloop *ioloop);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* Returns TRUE if there is a pending timeout that is going to be run
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen immediately. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenbool io_loop_have_immediate_timeouts(struct ioloop *ioloop);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen#endif
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen