1 | | | import 'dart:async'; |
2 | | |
|
3 | | | import '../_impl/xplat/_time_stamp.dart'; |
4 | | | import '../exceptions/task_canceled_exception.dart'; |
5 | | | import '../stats/perf_counter.dart'; |
6 | | | import '../worker/worker.dart'; |
7 | | | import 'task.dart'; |
8 | | | import 'worker_pool.dart'; |
9 | | |
|
10 | | | /// [WorkerTask] registered in the [WorkerPool]. |
11 | | | abstract base class WorkerTask<T, W extends Worker> implements Task<T> { |
12 | | 12 | WorkerTask(this._counter) : submitted = microsecTimeStamp(); |
13 | | |
|
14 | | | final int submitted; |
15 | | | int? _scheduled; |
16 | | | int? _finished; |
17 | | | int? _canceled; |
18 | | |
|
19 | | | final PerfCounter? _counter; |
20 | | |
|
21 | | | final _done = Completer<void>(); |
22 | | |
|
23 | | | /// Returns a future that will complete when the task has run. |
24 | | 1 | @override |
25 | | 3 | Future<void> get done => _done.future; |
26 | | |
|
27 | | 4 | @override |
28 | | 8 | bool get isCanceled => _canceled != null; |
29 | | |
|
30 | | 1 | @override |
31 | | 3 | bool get isPending => _scheduled == null && _canceled == null; |
32 | | |
|
33 | | 2 | @override |
34 | | 2 | bool get isFinished => |
35 | | 8 | _scheduled != null && _finished != null && _canceled == null; |
36 | | |
|
37 | | 2 | @override |
38 | | 2 | bool get isRunning => |
39 | | 7 | _scheduled != null && _finished == null && _canceled == null; |
40 | | |
|
41 | | 1 | @override |
42 | | 2 | Duration get runningTime => _scheduled == null |
43 | | 1 | ? Duration.zero |
44 | | 0 | : Duration( |
45 | | | microseconds: |
46 | | 1 | (_canceled ?? _finished ?? microsecTimeStamp()) - _scheduled!); |
47 | | |
|
48 | | 0 | @override |
49 | | 0 | Duration get waitTime => Duration( |
50 | | | microseconds: |
51 | | 0 | (_scheduled ?? _canceled ?? microsecTimeStamp()) - submitted); |
52 | | |
|
53 | | | TaskCanceledException? _canceledException; |
54 | | 6 | TaskCanceledException? get canceledException => _canceledException; |
55 | | |
|
56 | | 4 | void throwIfCanceled() { |
57 | | 8 | if (_canceledException != null) throw _canceledException!; |
58 | | | } |
59 | | |
|
60 | | 2 | @override |
61 | | 2 | void cancel([String? message]) { |
62 | | 6 | _canceled ??= microsecTimeStamp(); |
63 | | 6 | _canceledException ??= TaskCanceledException(message); |
64 | | 4 | if (_scheduled == null) { |
65 | | | // task will not be scheduled, make sure it reports as completed |
66 | | 6 | _done.complete(); |
67 | | | } |
68 | | 2 | } |
69 | | |
|
70 | | 8 | void _success(bool res) { |
71 | | 12 | _finished ??= microsecTimeStamp(); |
72 | | 12 | _counter?.update(_finished! - _scheduled!, res); |
73 | | 12 | _done.complete(); |
74 | | 4 | } |
75 | | |
|
76 | | 0 | void _error(_) { |
77 | | 0 | _finished ??= microsecTimeStamp(); |
78 | | 0 | _counter?.update(_finished! - _scheduled!, false); |
79 | | 0 | _done.complete(); |
80 | | 0 | } |
81 | | |
|
82 | | 8 | Future<void> run(W worker) async { |
83 | | 12 | _scheduled ??= microsecTimeStamp(); |
84 | | |
|
85 | | 20 | return execute(worker).then(_success, onError: _error); |
86 | | 4 | } |
87 | | |
|
88 | | | Future<bool> execute(W worker); |
89 | | | } |