Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_timer.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 
12 
13 #if (NGX_THREADS)
14 ngx_mutex_t *ngx_event_timer_mutex;
15 #endif
16 
17 
19 static ngx_rbtree_node_t ngx_event_timer_sentinel;
20 
21 /*
22  * the event timer rbtree may contain the duplicate keys, however,
23  * it should not be a problem, because we use the rbtree to find
24  * a minimum timer value only
25  */
26 
29 {
30  ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
32 
33 #if (NGX_THREADS)
34 
35  if (ngx_event_timer_mutex) {
36  ngx_event_timer_mutex->log = log;
37  return NGX_OK;
38  }
39 
40  ngx_event_timer_mutex = ngx_mutex_init(log, 0);
41  if (ngx_event_timer_mutex == NULL) {
42  return NGX_ERROR;
43  }
44 
45 #endif
46 
47  return NGX_OK;
48 }
49 
50 
53 {
54  ngx_msec_int_t timer;
55  ngx_rbtree_node_t *node, *root, *sentinel;
56 
57  if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {
58  return NGX_TIMER_INFINITE;
59  }
60 
61  ngx_mutex_lock(ngx_event_timer_mutex);
62 
65 
66  node = ngx_rbtree_min(root, sentinel);
67 
68  ngx_mutex_unlock(ngx_event_timer_mutex);
69 
70  timer = (ngx_msec_int_t) (node->key - ngx_current_msec);
71 
72  return (ngx_msec_t) (timer > 0 ? timer : 0);
73 }
74 
75 
76 void
78 {
79  ngx_event_t *ev;
80  ngx_rbtree_node_t *node, *root, *sentinel;
81 
83 
84  for ( ;; ) {
85 
86  ngx_mutex_lock(ngx_event_timer_mutex);
87 
89 
90  if (root == sentinel) {
91  return;
92  }
93 
94  node = ngx_rbtree_min(root, sentinel);
95 
96  /* node->key <= ngx_current_time */
97 
98  if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) {
99  ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
100 
101 #if (NGX_THREADS)
102 
103  if (ngx_threaded && ngx_trylock(ev->lock) == 0) {
104 
105  /*
106  * We cannot change the timer of the event that is being
107  * handled by another thread. And we cannot easy walk
108  * the rbtree to find next expired timer so we exit the loop.
109  * However, it should be a rare case when the event that is
110  * being handled has an expired timer.
111  */
112 
114  "event %p is busy in expire timers", ev);
115  break;
116  }
117 #endif
118 
120  "event timer del: %d: %M",
121  ngx_event_ident(ev->data), ev->timer.key);
122 
124 
125  ngx_mutex_unlock(ngx_event_timer_mutex);
126 
127 #if (NGX_DEBUG)
128  ev->timer.left = NULL;
129  ev->timer.right = NULL;
130  ev->timer.parent = NULL;
131 #endif
132 
133  ev->timer_set = 0;
134 
135 #if (NGX_THREADS)
136  if (ngx_threaded) {
137  ev->posted_timedout = 1;
138 
140 
141  ngx_unlock(ev->lock);
142 
143  continue;
144  }
145 #endif
146 
147  ev->timedout = 1;
148 
149  ev->handler(ev);
150 
151  continue;
152  }
153 
154  break;
155  }
156 
157  ngx_mutex_unlock(ngx_event_timer_mutex);
158 }