@@ -2,15 +2,28 @@ import 'dart:async';
22import 'dart:collection' ;
33import 'dart:isolate' ;
44
5- class PortClient {
5+ abstract class PortClient {
6+ Future <T > post <T >(Object message);
7+ void fire (Object message);
8+
9+ factory PortClient .parent () {
10+ return ParentPortClient ();
11+ }
12+
13+ factory PortClient .child (SendPort upstream) {
14+ return ChildPortClient (upstream);
15+ }
16+ }
17+
18+ class ParentPortClient implements PortClient {
619 late Future <SendPort > sendPort;
720 ReceivePort receivePort = ReceivePort ();
821 bool closed = false ;
922 int _nextId = 1 ;
1023
1124 Map <int , Completer <Object ?>> handlers = HashMap ();
1225
13- PortClient () {
26+ ParentPortClient () {
1427 final initCompleter = Completer <SendPort >();
1528 sendPort = initCompleter.future;
1629 receivePort.listen ((message) {
@@ -54,19 +67,28 @@ class PortClient {
5467 }
5568 }
5669
70+ @override
5771 Future <T > post <T >(Object message) async {
5872 if (closed) {
5973 throw ClosedException ();
6074 }
6175 var completer = Completer <T >();
6276 var id = _nextId++ ;
6377 handlers[id] = completer;
64- (await sendPort).send (_RequestMessage (id, message));
78+ (await sendPort).send (_RequestMessage (id, message, receivePort.sendPort ));
6579 return await completer.future;
6680 }
6781
68- PortServer server () {
69- return PortServer (receivePort.sendPort);
82+ @override
83+ void fire (Object message) async {
84+ if (closed) {
85+ throw ClosedException ();
86+ }
87+ (await sendPort).send (_FireMessage (message));
88+ }
89+
90+ RequestPortServer server () {
91+ return RequestPortServer (receivePort.sendPort);
7092 }
7193
7294 close () async {
@@ -83,24 +105,104 @@ class PortClient {
83105 }
84106}
85107
108+ class SerializedPortClient {
109+ final SendPort sendPort;
110+
111+ SerializedPortClient (this .sendPort);
112+
113+ ChildPortClient open () {
114+ return ChildPortClient (sendPort);
115+ }
116+ }
117+
118+ class ChildPortClient implements PortClient {
119+ final SendPort sendPort;
120+ final ReceivePort receivePort = ReceivePort ();
121+ int _nextId = 1 ;
122+
123+ final Map <int , Completer <Object ?>> handlers = HashMap ();
124+
125+ ChildPortClient (this .sendPort) {
126+ receivePort.listen ((message) {
127+ if (message is _PortChannelResult ) {
128+ final handler = handlers.remove (message.requestId);
129+ assert (handler != null );
130+ if (message.success) {
131+ handler! .complete (message.result);
132+ } else {
133+ handler! .completeError (message.error, message.stackTrace);
134+ }
135+ }
136+ });
137+ }
138+
139+ @override
140+ Future <T > post <T >(Object message) async {
141+ var completer = Completer <T >();
142+ var id = _nextId++ ;
143+ handlers[id] = completer;
144+ sendPort.send (_RequestMessage (id, message, receivePort.sendPort));
145+ return await completer.future;
146+ }
147+
148+ @override
149+ void fire (Object message) {
150+ sendPort.send (_FireMessage (message));
151+ }
152+ }
153+
154+ class RequestPortServer {
155+ final SendPort port;
156+
157+ RequestPortServer (this .port);
158+
159+ open (Future <Object ?> Function (Object ? message) handle) {
160+ return PortServer .forSendPort (port, handle);
161+ }
162+ }
163+
86164class PortServer {
87- SendPort port;
88- late ReceivePort receivePort;
89- late Future <Object ?> Function (Object ? message) handle;
90-
91- PortServer (this .port);
92-
93- void init (Future <Object ?> Function (Object ? message) handle) {
94- this .handle = handle;
95- receivePort = ReceivePort ();
96- port.send (_InitMessage (receivePort.sendPort));
97- receivePort.listen ((message) async {
98- final request = message as _RequestMessage ;
99- try {
100- var result = await handle (request.message);
101- port.send (_PortChannelResult .success (request.id, result));
102- } catch (e, stacktrace) {
103- port.send (_PortChannelResult .error (request.id, e, stacktrace));
165+ final ReceivePort _receivePort = ReceivePort ();
166+ final Future <Object ?> Function (Object ? message) handle;
167+
168+ PortServer (this .handle) {
169+ _init ();
170+ }
171+
172+ PortServer .forSendPort (SendPort port, this .handle) {
173+ port.send (_InitMessage (_receivePort.sendPort));
174+ _init ();
175+ }
176+
177+ SendPort get sendPort {
178+ return _receivePort.sendPort;
179+ }
180+
181+ client () {
182+ return SerializedPortClient (sendPort);
183+ }
184+
185+ close () {
186+ _receivePort.close ();
187+ }
188+
189+ _init () {
190+ _receivePort.listen ((request) async {
191+ if (request is _FireMessage ) {
192+ handle (request.message);
193+ } else if (request is _RequestMessage ) {
194+ if (request.id == 0 ) {
195+ // Fire and forget
196+ handle (request.message);
197+ } else {
198+ try {
199+ var result = await handle (request.message);
200+ request.reply.send (_PortChannelResult .success (request.id, result));
201+ } catch (e, stacktrace) {
202+ request.reply
203+ .send (_PortChannelResult .error (request.id, e, stacktrace));
204+ }
205+ }
104206 }
105207 });
106208 }
@@ -114,11 +216,18 @@ class _InitMessage {
114216 _InitMessage (this .port);
115217}
116218
219+ class _FireMessage {
220+ final Object message;
221+
222+ const _FireMessage (this .message);
223+ }
224+
117225class _RequestMessage {
118226 final int id;
119227 final Object message;
228+ final SendPort reply;
120229
121- _RequestMessage (this .id, this .message);
230+ _RequestMessage (this .id, this .message, this .reply );
122231}
123232
124233class ClosedException implements Exception {
0 commit comments