• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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