diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-11-26 09:35:49 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-11-26 09:37:24 +0200 |
commit | aa530f352b0410150bfe94c821ae32c1378b9d02 (patch) | |
tree | fb27f277db0c7feaaf12ce43169d3b0b44e95c0f /include/libtf/fiber.h | |
parent | 4db830052d941d9c6de281bc9a2f6ac212c59ad8 (diff) | |
download | libtf-aa530f352b0410150bfe94c821ae32c1378b9d02.tar.bz2 libtf-aa530f352b0410150bfe94c821ae32c1378b9d02.tar.xz |
libtf: stackable timeouts
instead of having per-function argument, use a push/pop mechanism:
- multiple timers inside fiber use only one heap entry
- easy to chain multiple possibly blocking operations inside one
timeout block
Diffstat (limited to 'include/libtf/fiber.h')
-rw-r--r-- | include/libtf/fiber.h | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/include/libtf/fiber.h b/include/libtf/fiber.h index c3d87c6..ce3745b 100644 --- a/include/libtf/fiber.h +++ b/include/libtf/fiber.h @@ -19,27 +19,22 @@ #include <libtf/list.h> #include <libtf/heap.h> -#define TF_UCTX_H "uctx-setjmp.h" - /* Fiber wakeup reasons */ #define TF_WAKEUP_NONE 0 #define TF_WAKEUP_IMMEDIATE -EAGAIN #define TF_WAKEUP_KILL -EINTR -#define TF_WAKEUP_TIMEOUT -ETIMEDOUT +#define TF_WAKEUP_TIMEOUT -ETIME +#define TF_WAKEUP_THIS_TIMEOUT -ETIMEDOUT #define TF_WAKEUP_FD -EIO -/* Special timeouts for tf_schedule() */ -#define TF_NO_TIMEOUT -1 -#define TF_NO_TIMEOUT_CHANGE -2 +struct tf_poll_data { + int epoll_fd; + int num_waiters; +}; /* Scheduler */ struct tf_fiber; -struct tf_poll_data { - int epoll_fd; - int num_waiters; -}; - struct tf_scheduler { struct tf_list_head run_q; struct tf_heap_head heap; @@ -47,7 +42,6 @@ struct tf_scheduler { int num_fibers; tf_mtime_t scheduler_time; struct tf_poll_data poll_data; - }; struct tf_main_ctx { @@ -55,6 +49,11 @@ struct tf_main_ctx { char ** argv; }; +struct tf_timeout { + tf_mtime_t saved_timeout; + unsigned int timeout_change; +}; + static inline struct tf_scheduler *tf_get_scheduler(void) { @@ -86,18 +85,38 @@ void *tf_fiber_create(tf_fiber_proc fiber_main, int private_size); void *tf_fiber_get(void *data); void tf_fiber_put(void *data); -/* Scheduling and fiber management */ -void tf_exit(void) attribute_noreturn; -void tf_kill(void *fiber); +#define tf_timed(func, timeout) \ + ({ \ + struct tf_timeout __timeout; \ + tf_timeout_push(&__timeout, timeout); \ + tf_timeout_pop(&__timeout, (func)); \ + }) + +//* Scheduling and fiber management */ +void tf_timeout_push(struct tf_timeout *timeout, tf_mtime_diff_t milliseconds); +int __tf_timeout_pop(struct tf_timeout *timeout, int err); + +static inline int tf_timeout_pop(struct tf_timeout *timeout, int err) +{ + if (unlikely(timeout->timeout_change)) + return __tf_timeout_pop(timeout, err); + return err; +} -int tf_schedule(int milliseconds); +int tf_schedule(void); void tf_wakeup(struct tf_fiber *fiber, int wakeup_type); +void tf_exit(void) attribute_noreturn; +void tf_kill(void *fiber); int tf_yield(void); static inline -int tf_msleep(int milliseconds) +int tf_msleep(tf_mtime_diff_t milliseconds) { - return tf_schedule(milliseconds); + int r; + r = tf_timed(tf_schedule(), milliseconds); + if (r == TF_WAKEUP_THIS_TIMEOUT) + r = 0; + return r; } #endif |