Home | History | Annotate | Download | only in android
      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
    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
    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
    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
    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
    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
    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
    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
    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
    240 loopIo_wantRead(LoopIo* io)
    241 {
    242     io->clazz->wantRead(io->impl);
    243 }
    244 AINLINED void
    245 loopIo_wantWrite(LoopIo* io)
    246 {
    247     io->clazz->wantWrite(io->impl);
    248 }
    249 AINLINED void
    250 loopIo_dontWantRead(LoopIo* io)
    251 {
    252     io->clazz->dontWantRead(io->impl);
    253 }
    254 AINLINED void
    255 loopIo_dontWantWrite(LoopIo* io)
    256 {
    257     io->clazz->dontWantWrite(io->impl);
    258 }
    259 AINLINED unsigned
    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
    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
    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
    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
    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
    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
    337 looper_free(Looper* looper)
    338 {
    339     if (looper)
    340         looper->destroy(looper);
    341 }
    342 
    343 /* */
    344 
    345 #endif /* ANDROID_LOOPER_H */
    346