1 /* Copyright (C) 2010 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12 #ifndef ANDROID_LOOPER_H
13 #define ANDROID_LOOPER_H
14
15 #include <stddef.h>
16 #include <stdint.h>
17 #include <limits.h>
18 #include <android/utils/system.h>
19
20 /**********************************************************************
21 **********************************************************************
22 *****
23 ***** T I M E R E P R E S E N T A T I O N
24 *****
25 **********************************************************************
26 **********************************************************************/
27
28 /* An Duration represents a duration in milliseconds */
29 typedef int64_t Duration;
30
31 /* A special Duration value used to mean "infinite" */
32 #define DURATION_INFINITE ((Duration)INT64_MAX)
33
34 /**********************************************************************
35 **********************************************************************
36 *****
37 ***** E V E N T L O O P O B J E C T S
38 *****
39 **********************************************************************
40 **********************************************************************/
41
42
43 /* A Looper is an abstraction for an event loop, which can
44 * be implemented in different ways. For example, the UI program may
45 * want to implement a custom event loop on top of the SDL event queue,
46 * while the QEMU core would implement it on top of QEMU's internal
47 * main loop which works differently.
48 *
49 * Once you have a Looper pointer, you can register "watchers" that
50 * will trigger callbacks whenever certain events occur. Supported event
51 * types are:
52 *
53 * - timer expiration
54 * - i/o file descriptor input/output
55 *
56 * See the relevant documentation for these below.
57 *
58 * Once you have registered one or more watchers, you can call looper_run()
59 * which will run the event loop until looper_forceQuit() is called from a
60 * callback, or no more watchers are registered.
61 *
62 * You can register/unregister watchers from a callback, or call various
63 * Looper methods from them (e.g. looper_now(), looper_forceQuit(), etc..)
64 *
65 * You can create a new Looper by calling looper_newGeneric(). This provides
66 * a default implementation that can be used in all threads.
67 *
68 * For the QEMU core, you can grab a Looper pointer by calling
69 * looper_newCore() instead. Its implementation relies on top of
70 * the QEMU event loop instead.
71 */
72 typedef struct Looper Looper;
73
74 /* Create a new generic looper that can be used in any context / thread. */
75 Looper* looper_newGeneric(void);
76
77 /* Create a new looper which is implemented on top of the QEMU main event
78 * loop. You should only use this when implementing the emulator UI and Core
79 * features in a single program executable.
80 */
81 Looper* looper_newCore(void);
82
83
84 typedef struct LoopTimer LoopTimer;
85 typedef void (*LoopTimerFunc)(void* opaque);
86
87 typedef struct LoopIo LoopIo;
88 typedef void (*LoopIoFunc)(void* opaque, int fd, unsigned events);
89
90 struct Looper {
91 Duration (*now) (Looper* looper);
92 void (*timer_init)(Looper* looper, LoopTimer* timer, LoopTimerFunc callback, void* opaque);
93 void (*io_init) (Looper* looper, LoopIo* io, int fd, LoopIoFunc callback, void* opaque);
94 int (*run) (Looper* looper, Duration deadline_ms);
95 void (*forceQuit) (Looper* looper);
96 void (*destroy) (Looper* looper);
97 };
98
99
100
101 /**********************************************************************
102 **********************************************************************
103 *****
104 ***** T I M E R S
105 *****
106 **********************************************************************
107 **********************************************************************/
108
109
110 typedef struct LoopTimerClass LoopTimerClass;
111
112 struct LoopTimer {
113 LoopTimerClass* clazz;
114 void* impl;
115 };
116
117 struct LoopTimerClass {
118 void (*startRelative)(void* impl, Duration timeout_ms);
119 void (*startAbsolute)(void* impl, Duration deadline_ms);
120 void (*stop) (void* impl);
121 int (*isActive) (void* impl);
122 void (*done) (void* impl);
123 };
124
125 /* Initialize a LoopTimer with a callback and an 'opaque' value.
126 * Each timer belongs to only one looper object.
127 */
128 AINLINED void
loopTimer_init(LoopTimer * timer,Looper * looper,LoopTimerFunc callback,void * opaque)129 loopTimer_init(LoopTimer* timer,
130 Looper* looper,
131 LoopTimerFunc callback,
132 void* opaque)
133 {
134 looper->timer_init(looper, timer, callback, opaque);
135 }
136
137 /* Finalize a LoopTimer */
138 AINLINED void
loopTimer_done(LoopTimer * timer)139 loopTimer_done(LoopTimer* timer)
140 {
141 timer->clazz->done(timer->impl);
142 timer->clazz = NULL;
143 timer->impl = NULL;
144 }
145
146 /* Start a timer, i.e. arm it to expire in 'timeout_ms' milliseconds,
147 * unless loopTimer_stop() is called before that, or the timer is
148 * reprogrammed with another loopTimer_startXXX() call.
149 */
150 AINLINED void
loopTimer_startRelative(LoopTimer * timer,Duration timeout_ms)151 loopTimer_startRelative(LoopTimer* timer, Duration timeout_ms)
152 {
153 timer->clazz->startRelative(timer->impl, timeout_ms);
154 }
155
156 /* A variant of loopTimer_startRelative that fires on a given deadline
157 * in milliseconds instead. If the deadline already passed, the timer is
158 * automatically appended to the list of pending event watchers and will
159 * fire as soon as possible. Note that this can cause infinite loops
160 * in your code if you're not careful.
161 */
162 AINLINED void
loopTimer_startAbsolute(LoopTimer * timer,Duration deadline_ms)163 loopTimer_startAbsolute(LoopTimer* timer, Duration deadline_ms)
164 {
165 timer->clazz->startAbsolute(timer->impl, deadline_ms);
166 }
167
168 /* Stop a given timer */
169 AINLINED void
loopTimer_stop(LoopTimer * timer)170 loopTimer_stop(LoopTimer* timer)
171 {
172 timer->clazz->stop(timer->impl);
173 }
174
175 /* Returns true iff the timer is active / started */
176 AINLINED int
loopTimer_isActive(LoopTimer * timer)177 loopTimer_isActive(LoopTimer* timer)
178 {
179 return timer->clazz->isActive(timer->impl);
180 }
181
182 /**********************************************************************
183 **********************************************************************
184 *****
185 ***** F I L E D E S C R I P T O R S
186 *****
187 **********************************************************************
188 **********************************************************************/
189
190 typedef struct LoopIoClass LoopIoClass;
191
192 struct LoopIo {
193 LoopIoClass* clazz;
194 void* impl;
195 int fd;
196 };
197
198 /* Bitmasks about i/o events. Note that errors (e.g. network disconnections)
199 * are mapped to both read and write events. The idea is that a read() or
200 * write() will return 0 or even -1 on non-blocking file descriptors in this
201 * case.
202 *
203 * You can receive several events at the same time on a single LoopIo
204 *
205 * Socket connect()s are mapped to LOOP_IO_WRITE events.
206 * Socket accept()s are mapped to LOOP_IO_READ events.
207 */
208 enum {
209 LOOP_IO_READ = (1 << 0),
210 LOOP_IO_WRITE = (1 << 1),
211 };
212
213 struct LoopIoClass {
214 void (*wantRead)(void* impl);
215 void (*wantWrite)(void* impl);
216 void (*dontWantRead)(void* impl);
217 void (*dontWantWrite)(void* impl);
218 unsigned (*poll)(void* impl);
219 void (*done)(void* impl);
220 };
221
222 AINLINED void
loopIo_init(LoopIo * io,Looper * looper,int fd,LoopIoFunc callback,void * opaque)223 loopIo_init(LoopIo* io, Looper* looper, int fd, LoopIoFunc callback, void* opaque)
224 {
225 looper->io_init(looper, io, fd, callback, opaque);
226 io->fd = fd;
227 }
228
229 /* Note: This does not close the file descriptor! */
230 AINLINED void
loopIo_done(LoopIo * io)231 loopIo_done(LoopIo* io)
232 {
233 io->clazz->done(io->impl);
234 }
235
236 /* The following functions are used to indicate whether you want the callback
237 * to be fired when there is data to be read or when the file is ready to
238 * be written to. */
239 AINLINED void
loopIo_wantRead(LoopIo * io)240 loopIo_wantRead(LoopIo* io)
241 {
242 io->clazz->wantRead(io->impl);
243 }
244 AINLINED void
loopIo_wantWrite(LoopIo * io)245 loopIo_wantWrite(LoopIo* io)
246 {
247 io->clazz->wantWrite(io->impl);
248 }
249 AINLINED void
loopIo_dontWantRead(LoopIo * io)250 loopIo_dontWantRead(LoopIo* io)
251 {
252 io->clazz->dontWantRead(io->impl);
253 }
254 AINLINED void
loopIo_dontWantWrite(LoopIo * io)255 loopIo_dontWantWrite(LoopIo* io)
256 {
257 io->clazz->dontWantWrite(io->impl);
258 }
259 AINLINED unsigned
loopIo_poll(LoopIo * io)260 loopIo_poll(LoopIo* io)
261 {
262 return io->clazz->poll(io->impl);
263 }
264
265 /**********************************************************************
266 **********************************************************************
267 *****
268 ***** L O O P E R
269 *****
270 **********************************************************************
271 **********************************************************************/
272
273 AINLINED Duration
looper_now(Looper * looper)274 looper_now(Looper* looper)
275 {
276 return looper->now(looper);
277 }
278 /* Run the event loop, until looper_forceQuit() is called, or there is no
279 * more registered watchers for events/timers in the looper.
280 *
281 * The value returned indicates the reason:
282 * 0 -> normal exit through looper_forceQuit()
283 * EWOULDBLOCK -> there are not more watchers registered (the looper
284 * would loop infinitely)
285 */
286 AINLINED void
looper_run(Looper * looper)287 looper_run(Looper* looper)
288 {
289 (void) looper->run(looper, DURATION_INFINITE);
290 }
291
292 /* A variant of looper_run() that allows to run the event loop only
293 * until a certain timeout in milliseconds has passed.
294 *
295 * Returns the reason why the looper stopped:
296 * 0 -> normal exit through looper_forceQuit()
297 * EWOULDBLOCK -> there are not more watchers registered (the looper
298 * would loop infinitely)
299 * ETIMEDOUT -> timeout reached
300 *
301 */
302 AINLINED int
looper_runWithTimeout(Looper * looper,Duration timeout_ms)303 looper_runWithTimeout(Looper* looper, Duration timeout_ms)
304 {
305 if (timeout_ms != DURATION_INFINITE)
306 timeout_ms += looper_now(looper);
307
308 return looper->run(looper, timeout_ms);
309 }
310
311 /* Another variant of looper_run() that takes a deadline instead of a
312 * timeout. Same return values than looper_runWithTimeout()
313 */
314 AINLINED int
looper_runWithDeadline(Looper * looper,Duration deadline_ms)315 looper_runWithDeadline(Looper* looper, Duration deadline_ms)
316 {
317 return looper->run(looper, deadline_ms);
318 }
319
320 /* Call this function from within the event loop to force it to quit
321 * as soon as possible. looper_run() / _runWithTimeout() / _runWithDeadline()
322 * will then return 0.
323 */
324 AINLINED void
looper_forceQuit(Looper * looper)325 looper_forceQuit(Looper* looper)
326 {
327 looper->forceQuit(looper);
328 }
329
330 /* Destroy a given looper object. Only works for those created
331 * with looper_new(). Cannot be called within looper_run()!!
332 *
333 * NOTE: This assumes that the user has destroyed all its
334 * timers and ios properly
335 */
336 AINLINED void
looper_free(Looper * looper)337 looper_free(Looper* looper)
338 {
339 if (looper)
340 looper->destroy(looper);
341 }
342
343 /* */
344
345 #endif /* ANDROID_LOOPER_H */
346