ngx_event_timer.c revision e18a033b
1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevngx_rbtree_t              ngx_event_timer_rbtree;
14e18a033bSKonstantin Ananyevstatic ngx_rbtree_node_t  ngx_event_timer_sentinel;
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev/*
17e18a033bSKonstantin Ananyev * the event timer rbtree may contain the duplicate keys, however,
18e18a033bSKonstantin Ananyev * it should not be a problem, because we use the rbtree to find
19e18a033bSKonstantin Ananyev * a minimum timer value only
20e18a033bSKonstantin Ananyev */
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyevngx_int_t
23e18a033bSKonstantin Ananyevngx_event_timer_init(ngx_log_t *log)
24e18a033bSKonstantin Ananyev{
25e18a033bSKonstantin Ananyev    ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
26e18a033bSKonstantin Ananyev                    ngx_rbtree_insert_timer_value);
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev    return NGX_OK;
29e18a033bSKonstantin Ananyev}
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev
32e18a033bSKonstantin Ananyevngx_msec_t
33e18a033bSKonstantin Ananyevngx_event_find_timer(void)
34e18a033bSKonstantin Ananyev{
35e18a033bSKonstantin Ananyev    ngx_msec_int_t      timer;
36e18a033bSKonstantin Ananyev    ngx_rbtree_node_t  *node, *root, *sentinel;
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyev    if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {
39e18a033bSKonstantin Ananyev        return NGX_TIMER_INFINITE;
40e18a033bSKonstantin Ananyev    }
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyev    root = ngx_event_timer_rbtree.root;
43e18a033bSKonstantin Ananyev    sentinel = ngx_event_timer_rbtree.sentinel;
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyev    node = ngx_rbtree_min(root, sentinel);
46e18a033bSKonstantin Ananyev
47e18a033bSKonstantin Ananyev    timer = (ngx_msec_int_t) (node->key - ngx_current_msec);
48e18a033bSKonstantin Ananyev
49e18a033bSKonstantin Ananyev    return (ngx_msec_t) (timer > 0 ? timer : 0);
50e18a033bSKonstantin Ananyev}
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev
53e18a033bSKonstantin Ananyevvoid
54e18a033bSKonstantin Ananyevngx_event_expire_timers(void)
55e18a033bSKonstantin Ananyev{
56e18a033bSKonstantin Ananyev    ngx_event_t        *ev;
57e18a033bSKonstantin Ananyev    ngx_rbtree_node_t  *node, *root, *sentinel;
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev    sentinel = ngx_event_timer_rbtree.sentinel;
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev    for ( ;; ) {
62e18a033bSKonstantin Ananyev        root = ngx_event_timer_rbtree.root;
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyev        if (root == sentinel) {
65e18a033bSKonstantin Ananyev            return;
66e18a033bSKonstantin Ananyev        }
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev        node = ngx_rbtree_min(root, sentinel);
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev        /* node->key > ngx_current_msec */
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev        if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) {
73e18a033bSKonstantin Ananyev            return;
74e18a033bSKonstantin Ananyev        }
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
79e18a033bSKonstantin Ananyev                       "event timer del: %d: %M",
80e18a033bSKonstantin Ananyev                       ngx_event_ident(ev->data), ev->timer.key);
81e18a033bSKonstantin Ananyev
82e18a033bSKonstantin Ananyev        ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
83e18a033bSKonstantin Ananyev
84e18a033bSKonstantin Ananyev#if (NGX_DEBUG)
85e18a033bSKonstantin Ananyev        ev->timer.left = NULL;
86e18a033bSKonstantin Ananyev        ev->timer.right = NULL;
87e18a033bSKonstantin Ananyev        ev->timer.parent = NULL;
88e18a033bSKonstantin Ananyev#endif
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev        ev->timer_set = 0;
91e18a033bSKonstantin Ananyev
92e18a033bSKonstantin Ananyev        ev->timedout = 1;
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev        ev->handler(ev);
95e18a033bSKonstantin Ananyev    }
96e18a033bSKonstantin Ananyev}
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev
99e18a033bSKonstantin Ananyevngx_int_t
100e18a033bSKonstantin Ananyevngx_event_no_timers_left(void)
101e18a033bSKonstantin Ananyev{
102e18a033bSKonstantin Ananyev    ngx_event_t        *ev;
103e18a033bSKonstantin Ananyev    ngx_rbtree_node_t  *node, *root, *sentinel;
104e18a033bSKonstantin Ananyev
105e18a033bSKonstantin Ananyev    sentinel = ngx_event_timer_rbtree.sentinel;
106e18a033bSKonstantin Ananyev    root = ngx_event_timer_rbtree.root;
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyev    if (root == sentinel) {
109e18a033bSKonstantin Ananyev        return NGX_OK;
110e18a033bSKonstantin Ananyev    }
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev    for (node = ngx_rbtree_min(root, sentinel);
113e18a033bSKonstantin Ananyev         node;
114e18a033bSKonstantin Ananyev         node = ngx_rbtree_next(&ngx_event_timer_rbtree, node))
115e18a033bSKonstantin Ananyev    {
116e18a033bSKonstantin Ananyev        ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
117e18a033bSKonstantin Ananyev
118e18a033bSKonstantin Ananyev        if (!ev->cancelable) {
119e18a033bSKonstantin Ananyev            return NGX_AGAIN;
120e18a033bSKonstantin Ananyev        }
121e18a033bSKonstantin Ananyev    }
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev    /* only cancelable timers left */
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev    return NGX_OK;
126e18a033bSKonstantin Ananyev}
127