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 | |
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')
-rw-r--r-- | include/libtf/fiber.h | 55 | ||||
-rw-r--r-- | include/libtf/heap.h | 6 | ||||
-rw-r--r-- | include/libtf/io.h | 19 |
3 files changed, 52 insertions, 28 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 diff --git a/include/libtf/heap.h b/include/libtf/heap.h index 24f4767..a68e01d 100644 --- a/include/libtf/heap.h +++ b/include/libtf/heap.h @@ -61,6 +61,12 @@ int tf_heap_empty(struct tf_heap_head *head) } static inline +int tf_heap_node_active(struct tf_heap_node *node) +{ + return node->index != 0; +} + +static inline int tf_heap_prealloc(struct tf_heap_head *head, uint32_t size) { if (unlikely(head->num_items + TF_HEAP_ITEM0 >= head->allocated)) diff --git a/include/libtf/io.h b/include/libtf/io.h index 38dd541..1f0b793 100644 --- a/include/libtf/io.h +++ b/include/libtf/io.h @@ -52,27 +52,26 @@ void tf_poll_close(void); int tf_open_fd(struct tf_fd *fd, int kfd, int flags); int tf_open(struct tf_fd *fd, const char *pathname, int flags); int tf_close(struct tf_fd *fd); -ssize_t tf_read(struct tf_fd *fd, void *buf, size_t count, tf_mtime_diff_t timeout); -ssize_t tf_write(struct tf_fd *fd, const void *buf, size_t count, tf_mtime_diff_t timeout); -int tf_read_fully(struct tf_fd *fd, void *buf, size_t count, tf_mtime_diff_t timeout); -int tf_write_fully(struct tf_fd *fd, const void *buf, size_t count, tf_mtime_diff_t timeout); +ssize_t tf_read(struct tf_fd *fd, void *buf, size_t count); +ssize_t tf_write(struct tf_fd *fd, const void *buf, size_t count); +int tf_read_fully(struct tf_fd *fd, void *buf, size_t count); +int tf_write_fully(struct tf_fd *fd, const void *buf, size_t count); int tf_socket(struct tf_fd *fd, int domain, int type, int protocol); int tf_bind(struct tf_fd *fd, const struct tf_sockaddr *addr); int tf_listen(struct tf_fd *fd, int backlog); int tf_accept(struct tf_fd *listen_fd, struct tf_fd *child_fd, - struct tf_sockaddr *from, tf_mtime_diff_t timeout); -int tf_connect(struct tf_fd *fd, const struct tf_sockaddr *addr, tf_mtime_diff_t timeout); + struct tf_sockaddr *from); +int tf_connect(struct tf_fd *fd, const struct tf_sockaddr *addr); ssize_t tf_recvmsg(struct tf_fd *fd, struct tf_sockaddr *from, struct tf_sockaddr *to, - void *buf, size_t count, tf_mtime_diff_t timeout); + void *buf, size_t count); ssize_t tf_sendmsg(struct tf_fd *fd, struct tf_sockaddr *from, const struct tf_sockaddr *to, - const void *buf, size_t count, tf_mtime_diff_t timeout); + const void *buf, size_t count); -int tf_query_dns(const char *name, int num_res, struct tf_sockaddr *res, - tf_mtime_diff_t timeout); +int tf_query_dns(const char *name, int num_res, struct tf_sockaddr *res); #endif |