| Index: mojo/public/dart/src/handle_watcher.dart
|
| diff --git a/mojo/public/dart/src/handle_watcher.dart b/mojo/public/dart/src/handle_watcher.dart
|
| index 5f056549d8517dd64ccfb8aa549bd6969493266d..1af15fd9c4b9e752b922b7261d8f8f91fe9e47cc 100644
|
| --- a/mojo/public/dart/src/handle_watcher.dart
|
| +++ b/mojo/public/dart/src/handle_watcher.dart
|
| @@ -45,7 +45,8 @@ class MojoHandleWatcher {
|
| static const int REMOVE = 1;
|
| static const int TOGGLE_WRITE = 2;
|
| static const int CLOSE = 3;
|
| - static const int SHUTDOWN = 4;
|
| + static const int TIMER = 4;
|
| + static const int SHUTDOWN = 5;
|
|
|
| static int _encodeCommand(int cmd, [int signals = 0]) =>
|
| (cmd << 2) | (signals & MojoHandleSignals.READWRITE);
|
| @@ -75,6 +76,9 @@ class MojoHandleWatcher {
|
| // a RawMojoHandle.
|
| RawMojoHandle _tempHandle;
|
|
|
| + // Priority queue of timers registered with the watcher.
|
| + TimerQueue _timerQueue;
|
| +
|
| MojoHandleWatcher(this._controlHandle) :
|
| _shutdown = false,
|
| _handles = new List<int>(),
|
| @@ -82,7 +86,8 @@ class MojoHandleWatcher {
|
| _signals = new List<int>(),
|
| _handleIndices = new Map<int, int>(),
|
| _handleCount = 1,
|
| - _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID) {
|
| + _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID),
|
| + _timerQueue = new TimerQueue() {
|
| // Setup control handle.
|
| _handles.add(_controlHandle);
|
| _ports.add(null); // There is no port for the control handle.
|
| @@ -90,11 +95,13 @@ class MojoHandleWatcher {
|
| _handleIndices[_controlHandle] = 0;
|
| }
|
|
|
| - static void _handleWatcherIsolate(MojoHandleWatcher watcher) {
|
| + static void _handleWatcherIsolate(int consumerHandle) {
|
| + MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
|
| while (!watcher._shutdown) {
|
| + int deadline = watcher._processTimerDeadlines();
|
| int res = RawMojoHandle.waitMany(watcher._handles,
|
| watcher._signals,
|
| - RawMojoHandle.DEADLINE_INDEFINITE);
|
| + deadline);
|
| if (res == 0) {
|
| watcher._handleControlMessage();
|
| } else if (res > 0) {
|
| @@ -103,7 +110,7 @@ class MojoHandleWatcher {
|
| watcher._routeEvent(res);
|
| // Remove the handle from the list.
|
| watcher._removeHandle(handle);
|
| - } else {
|
| + } else if (res != MojoResult.kDeadlineExceeded) {
|
| // Some handle was closed, but not by us.
|
| // We have to go through the list and find it.
|
| watcher._pruneClosedHandles();
|
| @@ -133,8 +140,8 @@ class MojoHandleWatcher {
|
|
|
| void _handleControlMessage() {
|
| List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle);
|
| - // result[0] = mojo handle if any
|
| - // result[1] = SendPort if any
|
| + // result[0] = mojo handle if any, or a timer deadline in milliseconds.
|
| + // result[1] = SendPort if any.
|
| // result[2] = command << 2 | WRITABLE | READABLE
|
|
|
| int signals = result[2] & MojoHandleSignals.READWRITE;
|
| @@ -152,6 +159,9 @@ class MojoHandleWatcher {
|
| case CLOSE:
|
| _close(result[0]);
|
| break;
|
| + case TIMER:
|
| + _timer(result[1], result[0]);
|
| + break;
|
| case SHUTDOWN:
|
| _shutdownHandleWatcher();
|
| break;
|
| @@ -217,6 +227,22 @@ class MojoHandleWatcher {
|
| _removeHandle(mojoHandle);
|
| }
|
|
|
| + // Returns the next timer deadline in units of microseconds from 'now'.
|
| + int _processTimerDeadlines() {
|
| + int now = (new DateTime.now()).millisecondsSinceEpoch;
|
| + while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) {
|
| + _timerQueue.currentPort.send(null);
|
| + _timerQueue.removeCurrent();
|
| + now = (new DateTime.now()).millisecondsSinceEpoch;
|
| + }
|
| + return _timerQueue.hasTimer ? (_timerQueue.currentTimeout - now) * 1000
|
| + : RawMojoHandle.DEADLINE_INDEFINITE;
|
| + }
|
| +
|
| + void _timer(SendPort port, int deadline) {
|
| + _timerQueue.updateTimer(port, deadline);
|
| + }
|
| +
|
| void _toggleWrite(int mojoHandle) {
|
| int idx = _handleIndices[mojoHandle];
|
| if (idx == null) {
|
| @@ -274,14 +300,11 @@ class MojoHandleWatcher {
|
| int consumerHandle = pipe.endpoints[0].handle.h;
|
| int producerHandle = pipe.endpoints[1].handle.h;
|
|
|
| - // Make a MojoHandleWatcher with one end.
|
| - MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
|
| -
|
| // Call setControlHandle with the other end.
|
| _MojoHandleWatcherNatives.setControlHandle(producerHandle);
|
|
|
| // Spawn the handle watcher isolate with the MojoHandleWatcher,
|
| - return Isolate.spawn(_handleWatcherIsolate, watcher);
|
| + return Isolate.spawn(_handleWatcherIsolate, consumerHandle);
|
| }
|
|
|
| static void Stop() {
|
| @@ -292,6 +315,9 @@ class MojoHandleWatcher {
|
| int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
|
| var handle = new RawMojoHandle(controlHandle);
|
| handle.close();
|
| +
|
| + // Invalidate the control handle.
|
| + _MojoHandleWatcherNatives.setControlHandle(RawMojoHandle.INVALID);
|
| }
|
|
|
| static MojoResult close(RawMojoHandle mojoHandle) {
|
| @@ -309,4 +335,10 @@ class MojoHandleWatcher {
|
| static MojoResult remove(RawMojoHandle mojoHandle) {
|
| return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
|
| }
|
| +
|
| + static MojoResult timer(SendPort port, int deadline) {
|
| + // The deadline will be unwrapped before sending to the handle watcher.
|
| + return _sendControlData(
|
| + new RawMojoHandle(deadline), port, _encodeCommand(TIMER));
|
| + }
|
| }
|
|
|