17a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Copyright (C) 2010 The Android Open Source Project
27a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner**
37a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** This software is licensed under the terms of the GNU General Public
47a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** License version 2, as published by the Free Software Foundation, and
57a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** may be copied, distributed, and modified under those terms.
67a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner**
77a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** This program is distributed in the hope that it will be useful,
87a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of
97a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** GNU General Public License for more details.
117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner*/
127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#ifndef ANDROID_LOOPER_H
137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#define ANDROID_LOOPER_H
147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <stddef.h>
167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <stdint.h>
177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <limits.h>
181bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner#include <android/utils/system.h>
197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/**********************************************************************
217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****  T I M E   R E P R E S E N T A T I O N
247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/
277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* An Duration represents a duration in milliseconds */
297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef int64_t   Duration;
307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* A special Duration value used to mean "infinite" */
327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#define  DURATION_INFINITE       ((Duration)INT64_MAX)
337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/**********************************************************************
357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****  E V E N T   L O O P   O B J E C T S
387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/
417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* A Looper is an abstraction for an event loop, which can
447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * be implemented in different ways. For example, the UI program may
457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * want to implement a custom event loop on top of the SDL event queue,
467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * while the QEMU core would implement it on top of QEMU's internal
477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * main loop which works differently.
487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Once you have a Looper pointer, you can register "watchers" that
507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * will trigger callbacks whenever certain events occur. Supported event
517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * types are:
527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *   - timer expiration
547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *   - i/o file descriptor input/output
557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * See the relevant documentation for these below.
577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Once you have registered one or more watchers, you can call looper_run()
597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * which will run the event loop until looper_forceQuit() is called from a
607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * callback, or no more watchers are registered.
617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * You can register/unregister watchers from a callback, or call various
637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Looper methods from them (e.g. looper_now(), looper_forceQuit(), etc..)
647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * You can create a new Looper by calling looper_newGeneric(). This provides
667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * a default implementation that can be used in all threads.
677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * For the QEMU core, you can grab a Looper pointer by calling
697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * looper_newCore() instead. Its implementation relies on top of
707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * the QEMU event loop instead.
717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct Looper    Looper;
737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Create a new generic looper that can be used in any context / thread. */
757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerLooper*  looper_newGeneric(void);
767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Create a new looper which is implemented on top of the QEMU main event
787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * loop. You should only use this when implementing the emulator UI and Core
797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * features in a single program executable.
807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerLooper*  looper_newCore(void);
827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct LoopTimer LoopTimer;
857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef void (*LoopTimerFunc)(void* opaque);
867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct LoopIo    LoopIo;
887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef void (*LoopIoFunc)(void* opaque, int fd, unsigned events);
897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct Looper {
917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    Duration (*now)   (Looper* looper);
927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*timer_init)(Looper* looper, LoopTimer* timer, LoopTimerFunc callback, void* opaque);
937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*io_init)   (Looper* looper, LoopIo* io, int fd, LoopIoFunc callback, void* opaque);
941bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    int  (*run)       (Looper* looper, Duration deadline_ms);
957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*forceQuit) (Looper* looper);
967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*destroy)   (Looper* looper);
977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/**********************************************************************
1027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
1037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
1047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****  T I M E R S
1057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
1067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
1077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/
1087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct LoopTimerClass  LoopTimerClass;
1117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct LoopTimer {
1137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    LoopTimerClass*  clazz;
1147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void*            impl;
1157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
1167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct LoopTimerClass {
1187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*startRelative)(void* impl, Duration timeout_ms);
1197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*startAbsolute)(void* impl, Duration deadline_ms);
1207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*stop)         (void* impl);
1217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    int  (*isActive)     (void* impl);
1227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*done)         (void* impl);
1237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
1247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Initialize a LoopTimer with a callback and an 'opaque' value.
1267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Each timer belongs to only one looper object.
1277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
1281bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
1297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_init(LoopTimer*     timer,
1307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner               Looper*        looper,
1317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner               LoopTimerFunc  callback,
1327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner               void*          opaque)
1337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->timer_init(looper, timer, callback, opaque);
1357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Finalize a LoopTimer */
1381bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
1397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_done(LoopTimer* timer)
1407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->clazz->done(timer->impl);
1427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->clazz = NULL;
1437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->impl  = NULL;
1447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Start a timer, i.e. arm it to expire in 'timeout_ms' milliseconds,
1477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * unless loopTimer_stop() is called before that, or the timer is
1487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * reprogrammed with another loopTimer_startXXX() call.
1497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
1501bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
1517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_startRelative(LoopTimer* timer, Duration timeout_ms)
1527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->clazz->startRelative(timer->impl, timeout_ms);
1547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* A variant of loopTimer_startRelative that fires on a given deadline
1577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * in milliseconds instead. If the deadline already passed, the timer is
1587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * automatically appended to the list of pending event watchers and will
1597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * fire as soon as possible. Note that this can cause infinite loops
1607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * in your code if you're not careful.
1617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
1621bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
1637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_startAbsolute(LoopTimer* timer, Duration deadline_ms)
1647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->clazz->startAbsolute(timer->impl, deadline_ms);
1667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Stop a given timer */
1691bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
1707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_stop(LoopTimer* timer)
1717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    timer->clazz->stop(timer->impl);
1737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Returns true iff the timer is active / started */
1761bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED int
1777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopTimer_isActive(LoopTimer* timer)
1787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
1797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    return timer->clazz->isActive(timer->impl);
1807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
1817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/**********************************************************************
1837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
1847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
1857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****  F I L E   D E S C R I P T O R S
1867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
1877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
1887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/
1897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct LoopIoClass  LoopIoClass;
1917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct LoopIo {
1937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    LoopIoClass*  clazz;
1947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void*         impl;
1957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    int           fd;
1967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
1977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
1987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Bitmasks about i/o events. Note that errors (e.g. network disconnections)
1997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * are mapped to both read and write events. The idea is that a read() or
2007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * write() will return 0 or even -1 on non-blocking file descriptors in this
2017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * case.
2027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
2037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * You can receive several events at the same time on a single LoopIo
2047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
2057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Socket connect()s are mapped to LOOP_IO_WRITE events.
2067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Socket accept()s are mapped to LOOP_IO_READ events.
2077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
2087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerenum {
2097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    LOOP_IO_READ  = (1 << 0),
2107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    LOOP_IO_WRITE = (1 << 1),
2117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
2127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct LoopIoClass {
2147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*wantRead)(void* impl);
2157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*wantWrite)(void* impl);
2167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*dontWantRead)(void* impl);
2177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*dontWantWrite)(void* impl);
218a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner    unsigned (*poll)(void* impl);
2197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    void (*done)(void* impl);
2207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
2217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2221bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_init(LoopIo* io, Looper* looper, int fd, LoopIoFunc callback, void* opaque)
2247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->io_init(looper, io, fd, callback, opaque);
2267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->fd = fd;
2277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Note: This does not close the file descriptor! */
2301bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_done(LoopIo* io)
2327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->clazz->done(io->impl);
2347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* The following functions are used to indicate whether you want the callback
2377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * to be fired when there is data to be read or when the file is ready to
2387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * be written to. */
2391bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_wantRead(LoopIo* io)
2417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->clazz->wantRead(io->impl);
2437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2441bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_wantWrite(LoopIo* io)
2467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->clazz->wantWrite(io->impl);
2487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2491bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_dontWantRead(LoopIo* io)
2517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->clazz->dontWantRead(io->impl);
2537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2541bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerloopIo_dontWantWrite(LoopIo* io)
2567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->clazz->dontWantWrite(io->impl);
2587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
259a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' TurnerAINLINED unsigned
260a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' TurnerloopIo_poll(LoopIo* io)
261a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner{
262a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner    return io->clazz->poll(io->impl);
263a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner}
2647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/**********************************************************************
2667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
2677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
2687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****  L O O P E R
2697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *****
2707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************
2717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/
2727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2731bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED Duration
2741bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerlooper_now(Looper* looper)
2751bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner{
2761bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    return looper->now(looper);
2771bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner}
2787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Run the event loop, until looper_forceQuit() is called, or there is no
2797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * more registered watchers for events/timers in the looper.
2801bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *
2811bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * The value returned indicates the reason:
2821bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *    0           -> normal exit through looper_forceQuit()
2831bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *    EWOULDBLOCK -> there are not more watchers registered (the looper
2841bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *                   would loop infinitely)
2857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
2861bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
2877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerlooper_run(Looper* looper)
2887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2891bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    (void) looper->run(looper, DURATION_INFINITE);
2907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2921bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner/* A variant of looper_run() that allows to run the event loop only
2931bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * until a certain timeout in milliseconds has passed.
2941bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *
2951bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * Returns the reason why the looper stopped:
2961bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *    0           -> normal exit through looper_forceQuit()
2971bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *    EWOULDBLOCK -> there are not more watchers registered (the looper
2981bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *                   would loop infinitely)
2991bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *    ETIMEDOUT   -> timeout reached
3001bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner *
3011bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner */
3021bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED int
3031bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerlooper_runWithTimeout(Looper* looper, Duration timeout_ms)
3041bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner{
3051bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    if (timeout_ms != DURATION_INFINITE)
3061bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner        timeout_ms += looper_now(looper);
3071bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner
3081bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    return looper->run(looper, timeout_ms);
3091bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner}
3101bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner
3111bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner/* Another variant of looper_run() that takes a deadline instead of a
3121bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * timeout. Same return values than looper_runWithTimeout()
3131bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner */
3141bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED int
3151bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerlooper_runWithDeadline(Looper* looper, Duration deadline_ms)
3161bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner{
3171bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    return looper->run(looper, deadline_ms);
3181bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner}
3191bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner
3201bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner/* Call this function from within the event loop to force it to quit
3211bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * as soon as possible. looper_run() / _runWithTimeout() / _runWithDeadline()
3221bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * will then return 0.
3231bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner */
3241bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
3257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerlooper_forceQuit(Looper* looper)
3267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->forceQuit(looper);
3287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Destroy a given looper object. Only works for those created
3317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * with looper_new(). Cannot be called within looper_run()!!
3327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *
3337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * NOTE: This assumes that the user has destroyed all its
3347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *        timers and ios properly
3357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
3361bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' TurnerAINLINED void
3377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerlooper_free(Looper* looper)
3387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    if (looper)
3407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        looper->destroy(looper);
3417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* */
3447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#endif /* ANDROID_LOOPER_H */
346