Description
According to description of class SendPort, there is no way to close the SendPort instance and signal to bound ReceivePort
to generate done
event.
Lets consider the following example:
import "dart:async";
import "dart:isolate";
void entryPoint(SendPort sendPort) {
for (int i in [0,1,2,3,4,5,6,7,8,9]){
sendPort.send(i);
}
}
main() async {
ReceivePort receivePort = new ReceivePort();
Isolate isolate = await Isolate.spawn(
entryPoint,
receivePort.sendPort);
receivePort.listen(
(data) {
print("received: $data");
},
onDone:() {
print("done");
}
);
}
The program is quite simple and easy to understand.
Unfortunately program successfully prints received
for all digits, but it never prints done
It is necessary to call receivePort.close()
explicitly to trigger the event done
and finish the program.
But to prevent data loss, close()
must be called only when all data is received.
However detecting the moment, when all data is sent and received might be tricky and error prone.
Here are some options:
- Send some special value at the end of the data.
- Use isolate
onExitListener
- Use another pair of SendPort-ReceivePort to send the special value to indicate end of the data
I think that all these options have problems:
-
It is necessary to modify the essential functionality of the program (aka business logic). In the example we send integers and either have to make some integer value special (i.e. do not use it for business) or change type integer to
Object
and use some special object likeCapability
. In all cases we have to modify the sender and receiver and callreceivePort.close()
explicitly. The program will became less simple and easy to understand. -
There is a race condition between
isolate terminated
event and the business data. Since they are sent via different channels (i.e. SendPort-ReceivePort pairs) theisolate terminated
may arrive earlier than last digit, for example, and if we callreceivePort.close()
then last digit will be lost. -
There is a race condition between
end of data
value and business data. Some data may be lost similar way as in previous point.
The elegant solution would be to introduce method close()
in SendPort
. The method should signal to bound ReceivePort
to generate done
event. Therefore no other tricky solutions would be necessary.