| // Copyright (c) 2015, 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. |
| |
| library services.scheduler; |
| |
| import 'dart:async'; |
| import 'dart:collection'; |
| |
| class TaskScheduler { |
| final Queue<_Task<dynamic>> _taskQueue = Queue<_Task<dynamic>>(); |
| bool _isActive = false; |
| |
| int get queueCount => _taskQueue.length; |
| |
| Future<T> _performTask<T>(Task<T> task) { |
| if (task.timeoutDuration != null) { |
| return task.perform().timeout(task.timeoutDuration); |
| } else { |
| return task.perform(); |
| } |
| } |
| |
| Future<T> schedule<T>(Task<T> task) { |
| if (!_isActive) { |
| _isActive = true; |
| return _performTask(task).whenComplete(_next); |
| } |
| final taskResult = Completer<T>(); |
| _taskQueue.add(_Task<T>(task, taskResult)); |
| return taskResult.future; |
| } |
| |
| void _next() { |
| assert(_isActive); |
| if (_taskQueue.isEmpty) { |
| _isActive = false; |
| return; |
| } |
| final first = _taskQueue.removeFirst(); |
| first.taskResult.complete(_performTask(first.task).whenComplete(_next)); |
| } |
| } |
| |
| // Internal unit of scheduling. |
| class _Task<T> { |
| final Task<T> task; |
| final Completer<T> taskResult; |
| _Task(this.task, this.taskResult); |
| } |
| |
| // Public working data structure. |
| abstract class Task<T> { |
| Future<T> perform(); |
| Duration timeoutDuration; |
| } |
| |
| class ClosureTask<T> extends Task<T> { |
| final Future<T> Function() _closure; |
| |
| ClosureTask(this._closure, {Duration timeoutDuration}) { |
| this.timeoutDuration = timeoutDuration; |
| } |
| |
| @override |
| Future<T> perform() { |
| return _closure(); |
| } |
| } |