| 1 |  |  | import 'dart:async'; | 
                
                
                    | 2 |  |  |  | 
                
                
                    | 3 |  |  | import 'package:cancelation_token/cancelation_token.dart'; | 
                
                
                    | 4 |  |  |  | 
                
                
                    | 5 |  |  | import '../exceptions/squadron_canceled_exception.dart'; | 
                
                
                    | 6 |  |  | import '../exceptions/squadron_error.dart'; | 
                
                
                    | 7 |  |  | import '../worker/worker_request.dart'; | 
                
                
                    | 8 |  |  | import '_squadron_cancelation_token.dart'; | 
                
                
                    | 9 |  |  |  | 
                
                
                    | 10 |  |  | /// Cancelation token reference. This special cancelation token is managed by the [WorkerMonitor] and is used to | 
                
                
                    | 11 |  |  | /// mirror cancelation tokens presented to Squadron by callers of a worker service. When a [WorkerRequest] is | 
                
                
                    | 12 |  |  | /// handled by the platform worker and that request is associated with a cancelation request, the [WorkerMonitor] | 
                
                
                    | 13 |  |  | /// will override the request's cancelation token with a [CancelationTokenReference]. The same cancelation may | 
                
                
                    | 14 |  |  | /// be used for several service calls, so the [WorkerMonitor] keeps a map of [CancelationTokenReference] and a | 
                
                
                    | 15 |  |  | /// reference count that is incremented for each [WorkerRequest] having the same cancelation token and decremented | 
                
                
                    | 16 |  |  | /// when processing is finished. When the reference count drops to 0 and the cancelation token was not canceled, | 
                
                
                    | 17 |  |  | /// the [CancelationTokenReference] is removed from the map. | 
                
                
                    | 18 |  |  | /// | 
                
                
                    | 19 |  |  | /// When a caller cancels a token, a cancelation notification is sent to all workers in the pool and the | 
                
                
                    | 20 |  |  | /// corresponding [CancelationTokenReference] will be canceled. Services executing in the context of a platform | 
                
                
                    | 21 |  |  | /// worker will be able to inspect the token's status to interrupt processing gracefully. If the token's status is | 
                
                
                    | 22 |  |  | /// not inspected, processing will continue in platform workers, but will be interrupted on caller-side with a | 
                
                
                    | 23 |  |  | /// [CanceledException]. | 
                
                
                    | 24 |  |  | class CancelationTokenReference implements SquadronCancelationToken { | 
                
                
                    | 25 |  | 10 |   CancelationTokenReference._noToken() | 
                
                
                    | 26 |  |  |       : _hasRef = false, | 
                
                
                    | 27 |  |  |         id = '' { | 
                
                
                    | 28 |  | 10 |     _refCount = 1; | 
                
                
                    | 29 |  |  |   } | 
                
                
                    | 30 |  |  |  | 
                
                
                    | 31 |  |  |   @override | 
                
                
                    | 32 |  |  |   final String id; | 
                
                
                    | 33 |  |  |  | 
                
                
                    | 34 |  |  |   /// Singleton token reference instance for requests containing no token. | 
                
                
                    | 35 |  | 30 |   static final noToken = CancelationTokenReference._noToken(); | 
                
                
                    | 36 |  |  |  | 
                
                
                    | 37 |  |  |   /// Creates a new token reference for [id]. | 
                
                
                    | 38 |  | 2 |   CancelationTokenReference(this.id) : _hasRef = true; | 
                
                
                    | 39 |  |  |  | 
                
                
                    | 40 |  | 0 |   @override | 
                
                
                    | 41 |  | 0 |   SquadronCanceledException? get exception => _exception; | 
                
                
                    | 42 |  |  |   SquadronCanceledException? _exception; | 
                
                
                    | 43 |  |  |  | 
                
                
                    | 44 |  | 0 |   @override | 
                
                
                    | 45 |  | 0 |   bool get isCanceled => (_exception != null); | 
                
                
                    | 46 |  |  |  | 
                
                
                    | 47 |  | 0 |   @override | 
                
                
                    | 48 |  | 0 |   Future<CanceledException> get onCanceled => _completer.future; | 
                
                
                    | 49 |  |  |   final _completer = Completer<SquadronCanceledException>(); | 
                
                
                    | 50 |  |  |  | 
                
                
                    | 51 |  |  |   /// Whether this token reference instance has a reference. A token reference | 
                
                
                    | 52 |  |  |   /// without a reference does nothing. | 
                
                
                    | 53 |  |  |   final bool _hasRef; | 
                
                
                    | 54 |  |  |  | 
                
                
                    | 55 |  |  |   /// Reference counter. | 
                
                
                    | 56 |  | 20 |   int get refCount => _refCount; | 
                
                
                    | 57 |  |  |   int _refCount = 0; | 
                
                
                    | 58 |  |  |  | 
                
                
                    | 59 |  |  |   /// Use this token reference for [request]. Increments the internal reference | 
                
                
                    | 60 |  |  |   /// counter and overrides [WorkerRequest.cancelToken] with this token. | 
                
                
                    | 61 |  | 10 |   void usedBy(WorkerRequest request) { | 
                
                
                    | 62 |  | 10 |     if (_hasRef) { | 
                
                
                    | 63 |  | 4 |       _refCount++; | 
                
                
                    | 64 |  | 2 |       request.overrideCancelToken(this); | 
                
                
                    | 65 |  | 10 |     } else if (request.cancelToken != null) { | 
                
                
                    | 66 |  | 0 |       throw SquadronErrorImpl.create('Token reference mismatch'); | 
                
                
                    | 67 |  |  |     } | 
                
                
                    | 68 |  |  |   } | 
                
                
                    | 69 |  |  |  | 
                
                
                    | 70 |  |  |   /// Release this token reference. Decrements the internal reference counter. | 
                
                
                    | 71 |  | 10 |   void release() { | 
                
                
                    | 72 |  | 10 |     if (_hasRef) { | 
                
                
                    | 73 |  | 4 |       _refCount--; | 
                
                
                    | 74 |  |  |     } | 
                
                
                    | 75 |  |  |   } | 
                
                
                    | 76 |  |  |  | 
                
                
                    | 77 |  | 2 |   void update(SquadronCancelationToken token) { | 
                
                
                    | 78 |  | 2 |     final ex = token.exception; | 
                
                
                    | 79 |  | 4 |     if (ex != null && !_completer.isCompleted) { | 
                
                
                    | 80 |  | 2 |       _exception = ex; | 
                
                
                    | 81 |  | 4 |       _completer.complete(ex); | 
                
                
                    | 82 |  |  |     } | 
                
                
                    | 83 |  |  |   } | 
                
                
                    | 84 |  |  |  | 
                
                
                    | 85 |  | 0 |   @override | 
                
                
                    | 86 |  |  |   void ensureStarted() {/* nothing to do */} | 
                
                
                    | 87 |  |  |  | 
                
                
                    | 88 |  | 0 |   @override | 
                
                
                    | 89 |  |  |   void throwIfCanceled() { | 
                
                
                    | 90 |  | 0 |     if (_exception != null) { | 
                
                
                    | 91 |  | 0 |       throw _exception!; | 
                
                
                    | 92 |  |  |     } | 
                
                
                    | 93 |  |  |   } | 
                
                
                    | 94 |  |  |  | 
                
                
                    | 95 |  | 0 |   @override | 
                
                
                    | 96 |  | 0 |   Future<void> refreshAndThrowIfCanceled() => Future(throwIfCanceled); | 
                
                
                    | 97 |  |  |  | 
                
                
                    | 98 |  | 0 |   @override | 
                
                
                    | 99 |  |  |   // no native cancelation token in workers | 
                
                
                    | 100 |  | 0 |   CancelationToken? get token => throw UnimplementedError(); | 
                
                
                    | 101 |  |  |  | 
                
                
                    | 102 |  | 0 |   @override | 
                
                
                    | 103 |  |  |   // serialization of token references | 
                
                
                    | 104 |  | 0 |   List serialize() => throw UnimplementedError(); | 
                
                
                    | 105 |  |  | } |