Chromium Code Reviews| Index: runtime/observatory/lib/src/elements/helpers/rendering_queue.dart |
| diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..660528a6a5376dbc1aa4ac1e5428d9619812a83b |
| --- /dev/null |
| +++ b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart |
| @@ -0,0 +1,72 @@ |
| +// Copyright (c) 2016, 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:html'; |
| +import 'dart:collection'; |
| +import 'dart:async'; |
| + |
| +/// A generic rendering task that can be scheduled. |
| +abstract class RenderingTask { |
| + /// Rendering synchronous callback. |
| + void render(); |
| +} |
| + |
| +/// A generic synchronization system for rendering operations. |
| +abstract class RenderingBarrier { |
| + /// Future to the next synchronization barrier (ms from application start). |
| + Future<num> get next; |
| +} |
| + |
| +/// Synchronization system based on the AnimationFrame. |
| +class NextAnimationFrameBarrier implements RenderingBarrier { |
| + Future<num> get next => window.animationFrame; |
| +} |
| + |
| +/// MOCK synchronization system for manual barrier triggering. |
| +class RenderingBarrierMock implements RenderingBarrier { |
| + final StreamController<num> _stream = new StreamController<num>.broadcast(); |
| + num _ms = 0; |
| + |
| + Future<num> get next => _stream.stream.first; |
| + |
| + /// Trigger the next barrier with an optional numer of ms elapsed. |
| + void triggerRenderingBarrier({num step: 20}) { |
| + assert(step != null); |
| + _stream.add(_ms += step); |
| + } |
| +} |
| + |
| +/// RenderingTask queuing and synchronization system. |
| +class RenderingQueue { |
| + final RenderingBarrier _barrier; |
| + final Queue<RenderingTask> _queue = new Queue<RenderingTask>(); |
| + |
| + bool get isEmpty => _queue.isEmpty; |
| + bool get isNotEmpty => _queue.isNotEmpty; |
| + |
| + /// Creates a RenderingQueue with the default synchronization barrier. |
| + RenderingQueue() : this.fromBarrier(new NextAnimationFrameBarrier()); |
| + |
| + /// Creates a RenderingQueue with a custom synchronization barrier. |
| + RenderingQueue.fromBarrier(this._barrier) { |
| + assert(this._barrier != null); |
| + } |
| + |
| + /// Add a task to the queue. |
| + /// If the current rendering phase is running it will be executed during this |
| + /// rendering cicle, otherwise it will be queued for the next one. |
|
rmacnak
2016/07/18 17:58:19
circle -> cycle
|
| + void enqueue(RenderingTask r) { |
| + assert(r != null); |
| + // If no task are in the queue there is no rendering phase scheduled. |
| + if (isEmpty) _render(); |
| + _queue.addLast(r); |
| + } |
| + |
| + Future _render() async { |
| + await _barrier.next; |
| + while (_queue.isNotEmpty) { |
| + _queue.removeFirst().render(); |
| + } |
| + } |
| +} |