Add isActive field on Timer.
BUG= http://dartbug.com/10010 R=floitsch@google.com Review URL: https://codereview.chromium.org//18325006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@24678 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -1360,6 +1360,16 @@ class TimerImpl implements Timer {
|
||||
TimerImpl(int milliseconds, void callback())
|
||||
: _once = true {
|
||||
if (milliseconds == 0 && (!hasTimer() || _globalState.isWorker)) {
|
||||
|
||||
void internalCallback() {
|
||||
_handle = null;
|
||||
callback();
|
||||
}
|
||||
|
||||
// Setting _handle to something different from null indicates that the
|
||||
// callback has not been run. Hence, the choice of 1 is arbitrary.
|
||||
_handle = 1;
|
||||
|
||||
// This makes a dependency between the async library and the
|
||||
// event loop of the isolate library. The compiler makes sure
|
||||
// that the event loop is compiled if [Timer] is used.
|
||||
@@ -1367,15 +1377,17 @@ class TimerImpl implements Timer {
|
||||
// loop instead of setTimeout, to make sure the futures get executed in
|
||||
// order.
|
||||
_globalState.topEventLoop.enqueue(
|
||||
_globalState.currentContext, callback, 'timer');
|
||||
_globalState.currentContext, internalCallback, 'timer');
|
||||
_inEventLoop = true;
|
||||
} else if (hasTimer()) {
|
||||
_globalState.topEventLoop.activeTimerCount++;
|
||||
|
||||
void internalCallback() {
|
||||
callback();
|
||||
_handle = null;
|
||||
_globalState.topEventLoop.activeTimerCount--;
|
||||
callback();
|
||||
}
|
||||
|
||||
_globalState.topEventLoop.activeTimerCount++;
|
||||
_handle = JS('int', '#.setTimeout(#, #)',
|
||||
globalThis,
|
||||
convertDartClosureToJS(internalCallback, 0),
|
||||
@@ -1416,6 +1428,8 @@ class TimerImpl implements Timer {
|
||||
throw new UnsupportedError("Canceling a timer.");
|
||||
}
|
||||
}
|
||||
|
||||
bool get isActive => _handle != null;
|
||||
}
|
||||
|
||||
bool hasTimer() => JS('', '#.setTimeout', globalThis) != null;
|
||||
|
||||
@@ -57,6 +57,16 @@ abstract class Timer {
|
||||
* Cancels the timer.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Returns whether the timer is still active.
|
||||
*
|
||||
* A non-periodic timer is active if the callback has not been executed,
|
||||
* and the timer has not been canceled.
|
||||
*
|
||||
* A periodic timer is active if it has not been canceled.
|
||||
*/
|
||||
bool get isActive;
|
||||
}
|
||||
|
||||
external Timer _createTimer(Duration duration, void callback());
|
||||
|
||||
@@ -436,7 +436,6 @@ class _ZoneTimer implements Timer {
|
||||
final _Zone _zone;
|
||||
final _TimerCallback _callback;
|
||||
Timer _timer;
|
||||
bool _isDone = false;
|
||||
|
||||
_ZoneTimer(this._zone, Duration duration, this._callback) {
|
||||
_zone.expectCallback();
|
||||
@@ -444,15 +443,15 @@ class _ZoneTimer implements Timer {
|
||||
}
|
||||
|
||||
void _run() {
|
||||
_isDone = true;
|
||||
_zone.executeCallbackGuarded(_callback);
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
if (!_isDone) _zone.cancelCallbackExpectation();
|
||||
_isDone = true;
|
||||
if (_timer.isActive) _zone.cancelCallbackExpectation();
|
||||
_timer.cancel();
|
||||
}
|
||||
|
||||
bool get isActive => _timer.isActive;
|
||||
}
|
||||
|
||||
typedef void _PeriodicTimerCallback(Timer timer);
|
||||
@@ -464,7 +463,6 @@ class _PeriodicZoneTimer implements Timer {
|
||||
final _Zone _zone;
|
||||
final _PeriodicTimerCallback _callback;
|
||||
Timer _timer;
|
||||
bool _isDone = false;
|
||||
|
||||
_PeriodicZoneTimer(this._zone, Duration duration, this._callback) {
|
||||
_zone.expectCallback();
|
||||
@@ -477,10 +475,11 @@ class _PeriodicZoneTimer implements Timer {
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
if (!_isDone) _zone.cancelCallbackExpectation();
|
||||
_isDone = true;
|
||||
if (_timer.isActive) _zone.cancelCallbackExpectation();
|
||||
_timer.cancel();
|
||||
}
|
||||
|
||||
bool get isActive => _timer.isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31009,31 +31009,44 @@ final _pureIsolatePrintClosure = (s) {
|
||||
|
||||
final _forwardingPrintClosure = _Utils.forwardingPrint;
|
||||
|
||||
class _Timer implements Timer {
|
||||
final canceller;
|
||||
class _Timer implements Timer {
|
||||
final _canceler;
|
||||
|
||||
_Timer(this.canceller);
|
||||
_Timer(int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
|
||||
void cancel() { canceller(); }
|
||||
if (repeating) {
|
||||
int id = window._setInterval(() {
|
||||
_canceler = null;
|
||||
callback(this);
|
||||
}, milliSeconds);)
|
||||
_canceler = () => window._clearInterval(id);
|
||||
} else {
|
||||
int id = window._setTimeout(() {
|
||||
_canceler = null;
|
||||
callback(this);
|
||||
}, milliSeconds); )
|
||||
_canceler = window._clearTimeout(id);
|
||||
}
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
if (_canceler != null) {
|
||||
_canceler();
|
||||
}
|
||||
_canceler = null;
|
||||
}
|
||||
|
||||
bool get isActive => _canceler != null;
|
||||
}
|
||||
|
||||
get _timerFactoryClosure => (int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
var maker;
|
||||
var canceller;
|
||||
if (repeating) {
|
||||
maker = window._setInterval;
|
||||
canceller = window._clearInterval;
|
||||
} else {
|
||||
maker = window._setTimeout;
|
||||
canceller = window._clearTimeout;
|
||||
}
|
||||
Timer timer;
|
||||
final int id = maker(() { callback(timer); }, milliSeconds);
|
||||
timer = new _Timer(() { canceller(id); });
|
||||
return timer;
|
||||
get _timerFactoryClosure =>
|
||||
(int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
return new _Timer(milliseconds, callback, repeating);
|
||||
};
|
||||
|
||||
|
||||
class _PureIsolateTimer implements Timer {
|
||||
bool _isDone = false;
|
||||
final ReceivePort _port = new ReceivePort();
|
||||
SendPort _sendPort; // Effectively final.
|
||||
|
||||
@@ -31043,6 +31056,7 @@ class _PureIsolateTimer implements Timer {
|
||||
_sendPort = _port.toSendPort();
|
||||
_port.receive((msg, replyTo) {
|
||||
assert(msg == _TIMER_PING);
|
||||
_isDone = !repeating;
|
||||
callback(this);
|
||||
if (!repeating) _cancel();
|
||||
});
|
||||
@@ -31056,12 +31070,15 @@ class _PureIsolateTimer implements Timer {
|
||||
}
|
||||
|
||||
void _cancel() {
|
||||
_isDone = true;
|
||||
_port.close();
|
||||
}
|
||||
|
||||
_send(msg) {
|
||||
_sendToHelperIsolate(msg, _sendPort);
|
||||
}
|
||||
|
||||
bool get isActive => !_isDone;
|
||||
}
|
||||
|
||||
get _pureIsolateTimerFactoryClosure =>
|
||||
|
||||
@@ -50,6 +50,7 @@ class _Timer extends LinkedListEntry<_Timer> implements Timer {
|
||||
|
||||
bool get _repeating => _milliSeconds >= 0;
|
||||
|
||||
bool get isActive => _callback != null;
|
||||
|
||||
// Cancels a set timer. The timer is removed from the timer list and if
|
||||
// the given timer is the earliest timer the native timer is reset.
|
||||
@@ -143,7 +144,12 @@ class _Timer extends LinkedListEntry<_Timer> implements Timer {
|
||||
// one of the later timers which will set the callback to
|
||||
// null.
|
||||
if (timer._callback != null) {
|
||||
timer._callback(timer);
|
||||
var callback = timer._callback;
|
||||
if (!timer._repeating) {
|
||||
//Mark timer as inactive.
|
||||
timer._callback = null;
|
||||
}
|
||||
callback(timer);
|
||||
// Re-insert repeating timer if not canceled.
|
||||
if (timer._repeating && timer._callback != null) {
|
||||
timer._advanceWakeupTime();
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import '../../../pkg/unittest/lib/unittest.dart';
|
||||
|
||||
main() {
|
||||
|
||||
test("timer isActive test", () {
|
||||
Timer t;
|
||||
|
||||
t = new Timer(const Duration(seconds: 1),
|
||||
expectAsync0(() => expect(t.isActive, equals(false))));
|
||||
expect(t.isActive, equals(true));
|
||||
});
|
||||
|
||||
test("periodic timer cancel test", () {
|
||||
Timer t;
|
||||
|
||||
int i = 0;
|
||||
void checkActive(Timer timer) {
|
||||
expect(t.isActive, equals(true));
|
||||
if (i == 2) {
|
||||
t.cancel();
|
||||
expect(t.isActive, equals(false));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
t = new Timer.periodic(new Duration(milliseconds: 1),
|
||||
expectAsync1(checkActive, count: 3));
|
||||
expect(t.isActive, equals(true));
|
||||
});
|
||||
|
||||
test("timer cancel test", () {
|
||||
Timer timer = new Timer(const Duration(seconds: 1),
|
||||
() => fail("Should not be reached."));
|
||||
Timer.run(expectAsync0(() {
|
||||
expect(timer.isActive, equals(true));
|
||||
timer.cancel();
|
||||
expect(timer.isActive, equals(false));
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -59,6 +59,7 @@ async/stream_periodic4_test: Fail # Timer interface not supported; dartbug.com/7
|
||||
async/stream_periodic5_test: Fail # Timer interface not supported; dartbug.com/7728.
|
||||
async/run_zoned7_test: Fail # Timer interface not supported: dartbug.com/7728.
|
||||
async/catch_errors22_test: Fail # Timer interface not supported: dartbug.com/7728.
|
||||
async/timer_isActive_test: Fail # Timer interface not supported: dartbug.com/7728.
|
||||
|
||||
[ $compiler == dart2js && $browser ]
|
||||
async/timer_not_available_test: Fail, OK # only meant to test when there is no way to
|
||||
|
||||
@@ -198,31 +198,43 @@ final _pureIsolatePrintClosure = (s) {
|
||||
|
||||
final _forwardingPrintClosure = _Utils.forwardingPrint;
|
||||
|
||||
class _Timer implements Timer {
|
||||
final canceller;
|
||||
class _Timer implements Timer{
|
||||
var _canceler;
|
||||
|
||||
_Timer(this.canceller);
|
||||
_Timer(int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
|
||||
void cancel() { canceller(); }
|
||||
if (repeating) {
|
||||
int id = window._setInterval(() {
|
||||
callback(this);
|
||||
}, milliSeconds);)
|
||||
_canceler = () => window._clearInterval(id);
|
||||
} else {
|
||||
int id = window._setTimeout(() {
|
||||
_canceler = null;
|
||||
callback(this);
|
||||
}, milliSeconds);)
|
||||
_canceler = () => window._clearTimeout(id);
|
||||
}
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
if (_canceler != null) {
|
||||
_canceler();
|
||||
}
|
||||
_canceler = null;
|
||||
}
|
||||
|
||||
bool get isActive => _canceler != null;
|
||||
}
|
||||
|
||||
get _timerFactoryClosure => (int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
var maker;
|
||||
var canceller;
|
||||
if (repeating) {
|
||||
maker = window._setInterval;
|
||||
canceller = window._clearInterval;
|
||||
} else {
|
||||
maker = window._setTimeout;
|
||||
canceller = window._clearTimeout;
|
||||
}
|
||||
Timer timer;
|
||||
final int id = maker(() { callback(timer); }, milliSeconds);
|
||||
timer = new _Timer(() { canceller(id); });
|
||||
return timer;
|
||||
get _timerFactoryClosure =>
|
||||
(int milliSeconds, void callback(Timer timer), bool repeating) {
|
||||
return new _Timer(milliseconds, callback, repeating);
|
||||
};
|
||||
|
||||
|
||||
class _PureIsolateTimer implements Timer {
|
||||
bool _isActive = true;
|
||||
final ReceivePort _port = new ReceivePort();
|
||||
SendPort _sendPort; // Effectively final.
|
||||
|
||||
@@ -232,6 +244,7 @@ class _PureIsolateTimer implements Timer {
|
||||
_sendPort = _port.toSendPort();
|
||||
_port.receive((msg, replyTo) {
|
||||
assert(msg == _TIMER_PING);
|
||||
_isActive = repeating;
|
||||
callback(this);
|
||||
if (!repeating) _cancel();
|
||||
});
|
||||
@@ -245,12 +258,15 @@ class _PureIsolateTimer implements Timer {
|
||||
}
|
||||
|
||||
void _cancel() {
|
||||
_isActive = false;
|
||||
_port.close();
|
||||
}
|
||||
|
||||
_send(msg) {
|
||||
_sendToHelperIsolate(msg, _sendPort);
|
||||
}
|
||||
|
||||
bool get isActive => _isActive;
|
||||
}
|
||||
|
||||
get _pureIsolateTimerFactoryClosure =>
|
||||
|
||||
Reference in New Issue
Block a user