1 | | | import 'dart:async'; |
2 | | |
|
3 | | | import 'package:cancelation_token/cancelation_token.dart'; |
4 | | | import 'package:meta/meta.dart'; |
5 | | |
|
6 | | | import '../_impl/xplat/_token_id.dart'; |
7 | | | import '../exceptions/squadron_canceled_exception.dart'; |
8 | | |
|
9 | | | class SquadronCancelationToken extends CancelationToken { |
10 | | 4 | SquadronCancelationToken._(this.token, this.id) { |
11 | | 10 | token?.onCanceled.then(_checkToken); |
12 | | 0 | } |
13 | | |
|
14 | | 2 | List serialize() { |
15 | | 4 | _checkToken(); |
16 | | 6 | return List.unmodifiable([ |
17 | | 4 | id, |
18 | | 6 | exception?.serialize(), |
19 | | | ]); |
20 | | 0 | } |
21 | | |
|
22 | | 10 | static SquadronCancelationToken? deserialize(List? props) { |
23 | | 1 | if (props == null) return null; |
24 | | 2 | final id = props[_$id]; |
25 | | 4 | final ex = SquadronCanceledExceptionExt.deserialize(props[_$ex]); |
26 | | 2 | final token = SquadronCancelationToken._(null, id); |
27 | | 0 | if (ex != null) { |
28 | | 2 | token._exception = ex; |
29 | | 4 | token._completer.complete(ex); |
30 | | | } |
31 | | 0 | return token; |
32 | | 1 | } |
33 | | |
|
34 | | | // cancelation token ID |
35 | | | final String id; |
36 | | |
|
37 | | | // reference to the real cancelation token (only set on the caller side, will |
38 | | | // be `null` in worker threads) |
39 | | | final CancelationToken? token; |
40 | | |
|
41 | | 2 | @override |
42 | | 4 | SquadronCanceledException? get exception => _exception; |
43 | | | SquadronCanceledException? _exception; |
44 | | |
|
45 | | 2 | @override |
46 | | 2 | void ensureStarted() { |
47 | | 5 | token?.ensureStarted(); |
48 | | 2 | } |
49 | | |
|
50 | | 2 | @override |
51 | | 6 | Future<CanceledException> get onCanceled => _completer.future; |
52 | | | final _completer = Completer<CanceledException>(); |
53 | | |
|
54 | | 4 | void _checkToken([dynamic _]) { |
55 | | 6 | final ex = token?.exception; |
56 | | 2 | if (ex != null) { |
57 | | 8 | _exception ??= SquadronCanceledException.from(id, ex); |
58 | | 6 | if (!_completer.isCompleted) { |
59 | | 8 | _completer.complete(_exception); |
60 | | | } |
61 | | | } |
62 | | 2 | } |
63 | | | } |
64 | | |
|
65 | | | const _$id = 0; |
66 | | | const _$ex = 1; |
67 | | |
|
68 | | | @internal |
69 | | | extension SquadronCancelationTokenExt on CancelationToken { |
70 | | 4 | SquadronCancelationToken wrap() { |
71 | | | final self = this; |
72 | | 2 | if (self is SquadronCancelationToken) return self; |
73 | | 4 | final token = SquadronCancelationToken._(self, TokenId.next()); |
74 | | 4 | token._checkToken(); |
75 | | 2 | return token; |
76 | | 2 | } |
77 | | | } |