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 137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "android/utils/assert.h" 147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "android/utils/reflist.h" 157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "android/utils/refset.h" 167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "android/utils/system.h" 177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "android/looper.h" 18d413fa5f2916a2a46494edb320340486b262644cDavid 'Digit' Turner#include "android/iolooper.h" 19cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h" 207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <inttypes.h> 217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <limits.h> 221bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner#include <errno.h> 237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/********************************************************************** 257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** T I M E R S 287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/ 317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct GLoopTimer GLoopTimer; 337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct GLoopIo GLoopIo; 347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct GLooper GLooper; 357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct GLoopTimer { 377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner Duration deadline; 387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopTimerFunc callback; 397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* opaque; 407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper; 417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* activeNext; 427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic Duration glooper_now(Looper* ll); 457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_addActiveTimer(GLooper* looper, GLoopTimer* timer); 477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_delActiveTimer(GLooper* looper, GLoopTimer* timer); 487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_addTimer(GLooper* looper, GLoopTimer* timer); 497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_delTimer(GLooper* looper, GLoopTimer* timer); 507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooptimer_stop(void* impl) 537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt = impl; 557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (tt->deadline != DURATION_INFINITE) { 567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_delActiveTimer(tt->looper, tt); 577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->deadline = DURATION_INFINITE; 587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooptimer_startAbsolute(void* impl, Duration deadline_ms) 637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt = impl; 657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Stop the timer if it was active */ 677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (tt->deadline != DURATION_INFINITE) 687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_stop(tt); 697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Another way to stop a timer */ 717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (deadline_ms == DURATION_INFINITE) 727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return; 737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->deadline = deadline_ms; 757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_addActiveTimer(tt->looper, tt); 767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooptimer_startRelative(void* impl, Duration timeout_ms) 807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt = impl; 827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (timeout_ms == DURATION_INFINITE) { /* another way to stop the timer */ 847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_stop(tt); 857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } else { 867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_startAbsolute(tt, timeout_ms + glooper_now((Looper*)tt->looper)); 877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic int 917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooptimer_isActive(void* impl) 927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt = impl; 947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return (tt->deadline != DURATION_INFINITE); 957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooptimer_free(void* impl) 997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt = impl; 1017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (tt->deadline != DURATION_INFINITE) 1037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_stop(tt); 1047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_delTimer(tt->looper, tt); 1067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner AFREE(tt); 1077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic const LoopTimerClass glooptimer_class = { 1107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_startRelative, 1117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_startAbsolute, 1127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_stop, 1137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_isActive, 1147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooptimer_free 1157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 1167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_timer_init(Looper* looper, 1197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopTimer* timer, 1207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopTimerFunc callback, 1217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* opaque) 1227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* tt; 1247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ANEW0(tt); 1267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->deadline = DURATION_INFINITE; 1287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->callback = callback; 1297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->opaque = opaque; 1307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->looper = (GLooper*) looper; 1317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_addTimer(tt->looper, tt); 1337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->impl = tt; 1357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->clazz = (LoopTimerClass*) &glooptimer_class; 1367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/********************************************************************** 1397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 1407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 1417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** I / O 1427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 1437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 1447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/ 1457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct GLoopIo { 1477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner int fd; 1487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopIoFunc callback; 1497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* opaque; 1507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned wanted; 1517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned ready; 1527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper; 1537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 1547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_delPendingIo(GLooper* looper, GLoopIo* io); 1567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_addIo(GLooper* looper, GLoopIo* io); 1577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_delIo(GLooper* looper, GLoopIo* io); 1587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void glooper_modifyFd(GLooper* looper, int fd, int oldwanted, int newwanted); 1597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* used to indicate that the set of wanted flags has changed */ 1617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_modify(GLoopIo* io, unsigned wanted) 1637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* If nothing changed, return */ 1657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->wanted == wanted) 1667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return; 1677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* If we are pending, and we're not interested by the 1697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * current ready flags, remove from list */ 1707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready != 0 && (io->ready & wanted) == 0) { 1717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_delPendingIo(io->looper, io); 1727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 1737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready &= wanted; 1747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_modifyFd(io->looper, io->fd, io->wanted, wanted); 1757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->wanted = wanted; 1767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_wantRead(void* impl) 1807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io = impl; 1827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_modify(io, io->wanted | LOOP_IO_READ); 1837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_wantWrite(void* impl) 1877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io = impl; 1897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_modify(io, io->wanted | LOOP_IO_WRITE); 1907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_dontWantRead(void* impl) 1947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io = impl; 1967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_modify(io, io->wanted & ~LOOP_IO_READ); 1977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_dontWantWrite(void* impl) 2017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io = impl; 2037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_modify(io, io->wanted & ~LOOP_IO_WRITE); 2047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 206a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turnerstatic unsigned 207a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turnergloopio_poll(void* impl) 208a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner{ 209a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner GLoopIo* io = impl; 210a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner return io->ready; 211a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner} 212a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner 2137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnergloopio_free(void* impl) 2157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io = impl; 2177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready != 0) 2187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_delPendingIo(io->looper, io); 2197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_delIo(io->looper, io); 2217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner AFREE(io); 2227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic LoopIoClass gloopio_class = { 2257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_wantRead, 2267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_wantWrite, 2277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_dontWantRead, 2287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_dontWantWrite, 229a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner gloopio_poll, 2307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner gloopio_free 2317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 2327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_io_init(Looper* looper, LoopIo* user, int fd, LoopIoFunc callback, void* opaque) 2357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* gg = (GLooper*)looper; 2377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopIo* io; 2387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ANEW0(io); 2407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->fd = fd; 2417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->callback = callback; 2427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->opaque = opaque; 2431bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner io->looper = (GLooper*) looper; 2447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->wanted = 0; 2457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready = 0; 2467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2471bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner socket_set_nonblock(fd); 2481bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 2497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner glooper_addIo(gg, io); 2507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner user->impl = io; 2527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner user->clazz = (LoopIoClass*) &gloopio_class; 2537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/********************************************************************** 2567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 2577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 2587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** L O O P E R 2597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 2607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 2617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/ 2627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct GLooper { 2647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner Looper looper; 2657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ARefSet timers[1]; /* set of all timers */ 2667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* activeTimers; /* sorted list of active timers */ 2677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ARefSet ios[1]; /* set of all i/o waiters */ 2697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ARefSet pendingIos[1]; /* list of pending i/o waiters */ 2701bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner int numActiveIos; /* number of active LoopIo objects */ 2717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner IoLooper* iolooper; 2737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner int running; 2747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 2757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_addTimer(GLooper* looper, GLoopTimer* tt) 2787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_add(looper->timers, tt); 2807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_delTimer(GLooper* looper, GLoopTimer* tt) 2847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_del(looper->timers, tt); 2867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_addActiveTimer(GLooper* looper, GLoopTimer* tt) 2907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner Duration deadline = tt->deadline; 2927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer** pnode = &looper->activeTimers; 2937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner for (;;) { 2947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* node = *pnode; 2957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (node == NULL || node->deadline > deadline) 2967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 2977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pnode = &node->activeNext; 2987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 2997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->activeNext = *pnode; 30007db34976ba1dd045a51c4ab2c7f52479cddcc57David 'Digit' Turner *pnode = tt; 3017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_delActiveTimer(GLooper* looper, GLoopTimer* tt) 3057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer** pnode = &looper->activeTimers; 3077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner for (;;) { 3087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == NULL) 3097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == tt) { 3117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *pnode = tt->activeNext; 3127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner tt->activeNext = NULL; 3137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pnode = &(*pnode)->activeNext; 3167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_addIo(GLooper* looper, GLoopIo* io) 3217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_add(looper->ios, io); 3237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_delIo(GLooper* looper, GLoopIo* io) 3277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_del(looper->ios, io); 3297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_delPendingIo(GLooper* looper, GLoopIo* io) 3337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_del(looper->pendingIos, io); 3357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_modifyFd(GLooper* looper, int fd, int oldWanted, int newWanted) 3397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3401bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner if (oldWanted == 0 && newWanted != 0) 3411bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner looper->numActiveIos += 1; 3421bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 3431bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner if (oldWanted != 0 && newWanted == 0) 3441bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner looper->numActiveIos -= 1; 3451bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 3467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner iolooper_modify(looper->iolooper, fd, oldWanted, newWanted); 3477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic Duration 3507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_now(Looper* ll) 3517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return iolooper_now(); 3537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_forceQuit(Looper* ll) 3577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper = (GLooper*)ll; 3597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->running = 0; 3607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3621bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerstatic int 3631bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerglooper_run(Looper* ll, Duration loop_deadline_ms) 3647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper = (GLooper*) ll; 3667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner IoLooper* iol = looper->iolooper; 3677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->running = 1; 3697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner while (looper->running) 3717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner { 3727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner int ret; 3737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3741bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner /* Exit prematurely if we detect that we don't have any active timer 3751bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * and no active LoopIo 3761bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner */ 3771bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner if (looper->numActiveIos == 0 && looper->activeTimers == NULL) 3781bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner return EWOULDBLOCK; 3791bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 3807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* First, compute next deadline */ 3817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner Duration deadline = DURATION_INFINITE; 3827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (looper->activeTimers != NULL) 3847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner deadline = looper->activeTimers->deadline; 3857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3861bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner if (deadline > loop_deadline_ms) 3871bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner deadline = loop_deadline_ms; 3881bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 3897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ret = iolooper_wait_absolute(iol, deadline); 3907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (ret < 0) { /* error, force stop ! */ 3917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (ret > 0) { 3947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned ready; 395347753be1d6bb07249641c84c3c582113af81941David 'Digit' Turner GLoopIo* io; 3967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Add io waiters to the pending list */ 398347753be1d6bb07249641c84c3c582113af81941David 'Digit' Turner AREFSET_FOREACH(looper->ios, io, { 3997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->wanted == 0) 4007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner continue; 4017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ready = 0; 4037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (iolooper_is_read(iol, io->fd)) 4057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ready |= LOOP_IO_READ; 4067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (iolooper_is_write(iol, io->fd)) 4087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ready |= LOOP_IO_WRITE; 4097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready = ready; 4117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (ready != 0) { 4127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_add(looper->pendingIos, io); 4137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner }); 4157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Do we have any expired timers here ? */ 4187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* pendingTimers = NULL; 4197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer** pendingLastP = &pendingTimers; 4207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner deadline = iolooper_now(); 4227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner for (;;) { 4237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* timer = looper->activeTimers; 4247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (timer == NULL || timer->deadline > deadline) 4257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 4267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* remove from active list, and append to pending one */ 4287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->deadline = DURATION_INFINITE; 4297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->activeTimers = timer->activeNext; 4307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *pendingLastP = timer; 4327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->activeNext = NULL; 4337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pendingLastP = &timer->activeNext; 4347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Fire the pending timers, if any. We do that in a separate 4377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * step because the callbacks could modify the active list 4387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * by starting/stopping other timers. 4397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */ 4407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner { 4417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLoopTimer* timer; 4427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner while ((timer = pendingTimers) != NULL) { 4437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pendingTimers = timer->activeNext; 4447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->activeNext = NULL; 4457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->callback(timer->opaque); 4467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Now fire the pending ios */ 4507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner { 451347753be1d6bb07249641c84c3c582113af81941David 'Digit' Turner GLoopIo* io; 452347753be1d6bb07249641c84c3c582113af81941David 'Digit' Turner AREFSET_FOREACH(looper->pendingIos,io,{ 4537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->callback(io->opaque,io->fd,io->ready); 4547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner }); 4557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_clear(looper->pendingIos); 4567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4571bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 4581bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner if (deadline > loop_deadline_ms) 4591bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner return ETIMEDOUT; 4607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 4611bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner return 0; 4627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 4637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 4657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerglooper_free(Looper* ll) 4667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 4677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper = (GLooper*)ll; 4687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_done(looper->timers); 4707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->activeTimers = NULL; 4717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_done(looper->ios); 4737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner arefSet_done(looper->pendingIos); 4747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner iolooper_free(looper->iolooper); 4767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->iolooper = NULL; 4777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner AFREE(looper); 4797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 4807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerLooper* looper_newGeneric(void) 4827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 4837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner GLooper* looper; 4847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ANEW0(looper); 4867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4871bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner looper->iolooper = iolooper_new(); 4881bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 4897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.now = glooper_now; 4907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.timer_init = glooper_timer_init; 4917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.io_init = glooper_io_init; 4927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.run = glooper_run; 4937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.forceQuit = glooper_forceQuit; 4947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.destroy = glooper_free; 4957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* Our implementation depends on these values being equal */ 4977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner AASSERT_INT(LOOP_IO_READ, IOLOOPER_READ); 4987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner AASSERT_INT(LOOP_IO_WRITE, IOLOOPER_WRITE); 4997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 5007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return &looper->looper; 5017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 502