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