1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2014 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #ifndef LCBIO_TIMER_H
19 #define LCBIO_TIMER_H
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif /** __cplusplus */
24 
25 /**
26  * @file
27  * @brief Timer Routines
28  *
29  * This file contains the timer routines. This provides a simpler interface
30  * than the one provided via the `lcb_timer_*` functions.
31  */
32 
33 /**
34  * @ingroup lcbio
35  * @defgroup lcbio-timers Timer Routines
36  *
37  * @details
38  *
39  * The timer routines here allow for an asynchronous event to be scheduled
40  * within a given amount of time, or "immediately". The basic idea is that
41  * these allow "Safe" invocation of routines without worrying about reentrancy
42  * issues.
43  *
44  * There is natually a performance hit in using these functions (since this needs
45  * to operate with the event loop) so this shouldn't be used for normal steady
46  * state operations (such as memcached operations).
47  *
48  * A timer may be created via lcbio_timer_new(). The timer's initial state
49  * is _unarmed_, meaning it will not be invoked until one of the scheduling
50  * routines are invoked.
51  *
52  * When a timer is armed, its callback (passed lcbio_timer_new()) will be
53  * invoked with the argument provided to lcbio_timer_new() as well.
54  *
55  * To schedule a timer, use the lcbio_timer_rearm() to unconditionally schedule
56  * an event within a certain timeframe, or lcbio_async_signal() to invoke the
57  * timer as soon as possible, once the event loop regains control.
58  *
59  * To cancel an armed timer (that is, to ensure the event is _not_ called), use
60  * the lcbio_timer_disarm() function or the lcbio_async_cancel() function (which
61  * itself is just an alias).
62  *
63  * Timers are not persistent, meaning that once they are fired they will enter
64  * an inactive state.
65  *
66  * @addtogroup lcbio-timers
67  * @{
68  */
69 
70 /** @private */
71 typedef enum {
72     LCBIO_TIMER_S_ENTERED = 0x01,
73     LCBIO_TIMER_S_DESTROYED = 0x02,
74     LCBIO_TIMER_S_ARMED = 0x04
75 } lcbio_TIMERSTATE;
76 
77 /**
78  * @brief Timer callback
79  * @see lcb_timer_new()
80  */
81 typedef void (*lcbio_TIMER_cb)(void *);
82 
83 typedef struct lcbio_TIMER {
84     void *event;
85     void *data;
86     lcbio_TIMER_cb callback;
87     uint32_t usec_;
88     lcbio_TIMERSTATE state;
89     lcbio_pTABLE io;
90 } lcbio_TIMER, lcbio_ASYNC;
91 
92 /**
93  * @brief Creates a new timer object.
94  *
95  * The newly created timer will be in an _unarmed_ state, but may
96  * may be activated with lcbio_timer_rearm()
97  *
98  * @param iot
99  * @param data
100  * @param callback
101  * @return A new timer object. Destroy with lcbio_timer_destroy()
102  */
103 lcbio_TIMER *
104 lcbio_timer_new(lcbio_pTABLE iot, void *data, lcbio_TIMER_cb callback);
105 
106 /**
107  * @brief Release the memory allocated by the timers
108  * @param tm the timer to free
109  */
110 void
111 lcbio_timer_destroy(lcbio_TIMER *tm);
112 
113 /**
114  * @brief Schedule the timer invocation
115  * @param timer The timer
116  * @param usec The number of microseconds (from now) in which the callback
117  * should be invoked
118  */
119 void
120 lcbio_timer_rearm(lcbio_TIMER *timer, uint32_t usec);
121 
122 /**
123  * @brief Cancel a pending invocation
124  * @param timer The timer
125  * If no pending invocation is present, this does nothing
126  */
127 void
128 lcbio_timer_disarm(lcbio_TIMER *timer);
129 
130 /**
131  * @brief Schedule an asynchronous call
132  * @param timer The timer to schedule
133  *
134  * This function is equivalent to calling
135  * @code{.c}
136  * lcbio_timer_rearm(timer, 0);
137  * @endcode
138  */
139 void
140 lcbio_async_signal(lcbio_TIMER *timer);
141 
142 /**
143  * @brief alias for lcbio_timer_disarm()
144  * @param timer
145  */
146 void
147 lcbio_async_cancel(lcbio_TIMER *timer);
148 
149 /**
150  * @brief Check if timer is armed
151  * @param timer the timer to inspect
152  * @return nonzero if armed, zero if unarmed.
153  */
154 #define lcbio_timer_armed(timer) ((timer)->state & LCBIO_TIMER_S_ARMED)
155 
156 /**
157  * Get the callback that is to be invoked for the timer
158  * @param timer the timer to query
159  * @return the current callback
160  * @see lcbio_timer_set_target()
161  */
162 #define lcbio_timer_get_target(timer) (timer)->callback
163 
164 /**
165  * Change the target callback for the timer
166  * @param timer the timer to modify
167  * @param tgt the target callback to set.
168  */
169 #define lcbio_timer_set_target(timer, tgt) (timer)->callback = tgt
170 
171 void
172 lcbio_timer_dump(lcbio_TIMER *timer, FILE *fp);
173 
174 /**@}*/
175 
176 #ifdef __cplusplus
177 }
178 #endif /** __cplusplus */
179 #endif /* LCBIO_TIMER_H */
180