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