compute<Q, R> function
- @experimental
- ComputeCallback<
Q, R> callback, - Q message, {
- String? debugLabel,
The dart:io implementation of compute.
Implementation
@experimental
Future<R> compute<Q, R>(
ComputeCallback<Q, R> callback,
Q message, {
String? debugLabel,
}) async {
debugLabel ??= const bool.fromEnvironment('dart.vm.product')
? 'compute'
: callback.toString();
final flow = Flow.begin();
Timeline.startSync('$debugLabel: start', flow: flow);
final port = RawReceivePort();
Timeline.finishSync();
void timeEndAndCleanup() {
Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
port.close();
Timeline.finishSync();
}
final completer = Completer<Object?>();
port.handler = (Object? msg) {
timeEndAndCleanup();
completer.complete(msg);
};
try {
await Isolate.spawn<_IsolateConfiguration<Q, R>>(
_spawn,
_IsolateConfiguration<Q, R>(
callback,
message,
port.sendPort,
debugLabel,
flow.id,
),
onExit: port.sendPort,
onError: port.sendPort,
debugName: debugLabel,
);
} on Object {
timeEndAndCleanup();
rethrow;
}
final response = await completer.future;
if (response == null) {
throw RemoteError('Isolate exited without result or error.', '');
}
assert(response is List<Object?>, 'Unexpected response type: $response');
response as List<Object?>;
final type = response.length;
assert(1 <= type && type <= 3, 'Unexpected response type: $type');
switch (type) {
// success; see _buildSuccessResponse
case 1:
return response[0] as R;
// native error; see Isolate.addErrorListener
case 2:
await Future<Never>.error(
RemoteError(
response[0]! as String,
response[1]! as String,
),
);
// caught error; see _buildErrorResponse
case 3:
default:
assert(
type == 3 && response[2] == null,
'Unexpected response type',
);
await Future<Never>.error(
response[0]!,
response[1]! as StackTrace,
);
}
}