From 7d5ef20bb1b20cec60fa0bbb81b2dd41eaefd5d1 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 27 Aug 2015 10:51:01 -0700 Subject: [PATCH] Scheduler should be able to cancel a queued callback Previously, once a callback was in the execution queue, it couldn't be canceled. Now we check whether the callback was canceled before executing it. --- sky/packages/sky/lib/base/scheduler.dart | 13 +++++--- sky/unit/test/base/scheduler_test.dart | 42 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 sky/unit/test/base/scheduler_test.dart diff --git a/sky/packages/sky/lib/base/scheduler.dart b/sky/packages/sky/lib/base/scheduler.dart index d1494412a0d..81a2fbbf331 100644 --- a/sky/packages/sky/lib/base/scheduler.dart +++ b/sky/packages/sky/lib/base/scheduler.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:collection'; import 'dart:sky' as sky; import 'package:sky/base/debug.dart'; @@ -12,9 +13,10 @@ bool _haveScheduledVisualUpdate = false; int _nextCallbackId = 1; final List _persistentCallbacks = new List(); -Map _transientCallbacks = new Map(); +Map _transientCallbacks = new LinkedHashMap(); +final Set _removedIds = new Set(); -void _beginFrame(double timeStamp) { +void beginFrame(double timeStamp) { timeStamp /= timeDilation; _haveScheduledVisualUpdate = false; @@ -23,15 +25,17 @@ void _beginFrame(double timeStamp) { _transientCallbacks = new Map(); callbacks.forEach((id, callback) { - callback(timeStamp); + if (!_removedIds.contains(id)) + callback(timeStamp); }); + _removedIds.clear(); for (Callback callback in _persistentCallbacks) callback(timeStamp); } void init() { - sky.view.setFrameCallback(_beginFrame); + sky.view.setFrameCallback(beginFrame); } void addPersistentFrameCallback(Callback callback) { @@ -47,6 +51,7 @@ int requestAnimationFrame(Callback callback) { void cancelAnimationFrame(int id) { _transientCallbacks.remove(id); + _removedIds.add(id); } void ensureVisualUpdate() { diff --git a/sky/unit/test/base/scheduler_test.dart b/sky/unit/test/base/scheduler_test.dart new file mode 100644 index 00000000000..a49379734ce --- /dev/null +++ b/sky/unit/test/base/scheduler_test.dart @@ -0,0 +1,42 @@ +import 'package:sky/base/scheduler.dart' as scheduler; +import 'package:test/test.dart'; + +void main() { + test("Can cancel queued callback", () { + int secondId; + + bool firstCallbackRan = false; + bool secondCallbackRan = false; + + void firstCallback(double timeStamp) { + expect(firstCallbackRan, isFalse); + expect(secondCallbackRan, isFalse); + expect(timeStamp, equals(16.0)); + firstCallbackRan = true; + scheduler.cancelAnimationFrame(secondId); + } + + void secondCallback(double timeStamp) { + expect(firstCallbackRan, isTrue); + expect(secondCallbackRan, isFalse); + expect(timeStamp, equals(16.0)); + secondCallbackRan = true; + } + + scheduler.requestAnimationFrame(firstCallback); + secondId = scheduler.requestAnimationFrame(secondCallback); + + scheduler.beginFrame(16.0); + + expect(firstCallbackRan, isTrue); + expect(secondCallbackRan, isFalse); + + firstCallbackRan = false; + secondCallbackRan = false; + + scheduler.beginFrame(32.0); + + expect(firstCallbackRan, isFalse); + expect(secondCallbackRan, isFalse); + }); +}