1
1
import 'dart:async' ;
2
2
import 'dart:isolate' ;
3
3
4
+ import 'package:logging/logging.dart' ;
5
+ import 'package:meta/meta.dart' ;
4
6
import 'package:sane/src/exceptions.dart' ;
7
+ import 'package:sane/src/extensions.dart' ;
5
8
import 'package:sane/src/isolate_messages/exception.dart' ;
9
+ import 'package:sane/src/isolate_messages/exit.dart' ;
6
10
import 'package:sane/src/isolate_messages/interface.dart' ;
7
11
import 'package:sane/src/sane.dart' ;
8
12
13
+ final _logger = Logger ('sane.isolate' );
14
+
15
+ @internal
9
16
class SaneIsolate {
10
17
SaneIsolate ._(
11
18
this ._isolate,
12
- this ._sendPort,
13
- this ._exitReceivePort,
14
- ) : _exited = false {
15
- _exitReceivePort.listen ((message) {
16
- assert (message == null );
17
- _exited = true ;
18
- });
19
- }
19
+ this ._sendPort,);
20
20
21
21
final Isolate _isolate;
22
22
final SendPort _sendPort;
23
- final ReceivePort _exitReceivePort;
24
-
25
- bool _exited;
26
-
27
- bool get exited => _exited;
28
23
29
24
static Future <SaneIsolate > spawn (Sane sane) async {
30
25
final receivePort = ReceivePort ();
31
- final exitReceivePort = ReceivePort ();
32
26
33
27
final isolate = await Isolate .spawn (
34
28
_entryPoint,
35
29
(receivePort.sendPort, sane),
36
- onExit: exitReceivePort .sendPort,
30
+ onExit: receivePort .sendPort,
37
31
);
38
32
39
- final sendPort = await receivePort.first as SendPort ;
40
- return SaneIsolate ._(isolate, sendPort, exitReceivePort);
41
- }
33
+ final sendPortCompleter = Completer <SendPort >();
34
+ receivePort.listen ((message) {
35
+ switch (message) {
36
+ case SendPort ():
37
+ sendPortCompleter.complete (message);
38
+ case LogRecord ():
39
+ _logger.redirect (message);
40
+ case null :
41
+ receivePort.close ();
42
+ }
43
+ });
42
44
43
- void kill () {
44
- _isolate. kill (priority : Isolate .immediate );
45
+ final sendPort = await sendPortCompleter.future;
46
+ return SaneIsolate ._(isolate, sendPort );
45
47
}
46
48
49
+ void kill () => _isolate.kill (priority: Isolate .immediate);
50
+
47
51
Future <T > sendMessage <T extends IsolateResponse >(
48
52
IsolateMessage <T > message,
49
53
) async {
@@ -75,10 +79,16 @@ typedef _EntryPointArgs = (SendPort sendPort, Sane sane);
75
79
void _entryPoint (_EntryPointArgs args) {
76
80
final (sendPort, sane) = args;
77
81
82
+ Logger .root.level = Level .ALL ;
83
+ Logger .root.onRecord.forEach (sendPort.send);
84
+
78
85
final receivePort = ReceivePort ();
79
86
sendPort.send (receivePort.sendPort);
80
87
81
- receivePort.cast <_IsolateMessageEnvelope >().listen ((envelope) async {
88
+ late StreamSubscription <_IsolateMessageEnvelope > subscription;
89
+
90
+ subscription =
91
+ receivePort.cast <_IsolateMessageEnvelope >().listen ((envelope) async {
82
92
final _IsolateMessageEnvelope (: message, : replyPort) = envelope;
83
93
84
94
IsolateResponse response;
@@ -93,6 +103,10 @@ void _entryPoint(_EntryPointArgs args) {
93
103
}
94
104
95
105
replyPort.send (response);
106
+
107
+ if (message is ExitMessage ) {
108
+ await subscription.cancel ();
109
+ }
96
110
});
97
111
}
98
112
@@ -108,8 +122,10 @@ class _IsolateMessageEnvelope {
108
122
109
123
late Map <String , SaneDevice > _devices;
110
124
125
+ @internal
111
126
SaneDevice getDevice (String name) => _devices[name]! ;
112
127
128
+ @internal
113
129
void setDevices (Iterable <SaneDevice > devices) {
114
130
_devices = {
115
131
for (final device in devices) device.name: device,
0 commit comments