4ccae238ea
TransferableTypedData instances are one-use kind of thing: once receiver materializes it, it can't be used
again, once sender sends it out to an isolate, sender can't send it to different isolate.
Example of use:
sender isolate:
```
Future<TransferableTypedData> consolidateHttpClientResponseBytes(HttpClientResponse response) {
final completer = Completer<TransferableTypedData>();
final chunks = <Uint8List>[];
response.listen((List<int> chunk) {
chunks.add(chunk);
}, onDone: () {
completer.complete(TransferableTypedData.fromList(chunks));
});
return completer.future;
}
...
sendPort.send(await consolidateHttpClientResponseBytes(response));
```
receiver isolate:
```
RawReceivePort port = RawReceivePort((TransferableTypedData transferable) {
Uint8List content = transferable.materialize().asUint8List();
...
});
```
31959[tr] and 31960[tr] tests were inspired by dartbug.com/31959, dartbug.com/31960 that this CL attempts to address:
```
╰─➤ out/ReleaseX64/dart 31960.dart
sending...
163ms for round-trip
sending...
81ms for round-trip
sending...
20ms for round-trip
sending...
14ms for round-trip
sending...
20ms for round-trip
sending...
14ms for round-trip
```
(notice no "since last checking" pauses") vs
```
╰─➤ out/ReleaseX64/dart 31960.dart
sending...
154ms since last checkin
174ms for round-trip
sending...
68ms since last checkin
9ms since last checkin
171ms for round-trip
sending...
13ms since last checkin
108ms for round-trip
sending...
14ms since last checkin
108ms for round-trip
sending...
14ms since last checkin
107ms for round-trip
```
Change-Id: I0fcb5ce285394f498c3f1db4414204531f98199d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99623
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
84 lines
3.1 KiB
Dart
84 lines
3.1 KiB
Dart
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import "dart:io" show ServerSocket;
|
|
import "dart:isolate";
|
|
import "dart:typed_data" show ByteData;
|
|
|
|
import "package:expect/expect.dart";
|
|
import "package:async_helper/async_helper.dart";
|
|
|
|
void main() async {
|
|
final port = new ReceivePort();
|
|
|
|
// Sending a socket object will result in an error.
|
|
final socket = await ServerSocket.bind('localhost', 0);
|
|
|
|
final x = new ByteData(4);
|
|
for (int i = 0; i < 4; i++) {
|
|
x.setUint8(i, i);
|
|
}
|
|
{
|
|
final transferableFirst = TransferableTypedData.fromList([x]);
|
|
Expect.throwsArgumentError(
|
|
() => port.sendPort.send(<dynamic>[transferableFirst, socket]));
|
|
// Once TransferableTypedData was sent even if attempt failed, it can't be
|
|
// materialized.
|
|
// This need to be changed so that on failed send we should not detach the
|
|
// buffer form the transferrable. The order should not matter (i.e. if the
|
|
// error happens before or after the serializer hits a transferrable object)
|
|
|
|
final data1 = transferableFirst.materialize().asUint8List();
|
|
Expect.equals(x.lengthInBytes, data1.length);
|
|
for (int i = 0; i < data1.length; i++) {
|
|
Expect.equals(i, data1[i]);
|
|
}
|
|
}
|
|
{
|
|
final transferableFirst = TransferableTypedData.fromList([x]);
|
|
Expect.throwsArgumentError(() => port.sendPort
|
|
.send(<dynamic>[transferableFirst, transferableFirst, socket]));
|
|
// Once TransferableTypedData was sent even if attempt failed, it can't be
|
|
// materialized.
|
|
// This need to be changed so that on failed send we should not detach the
|
|
// buffer form the transferrable. The order should not matter (i.e. if the
|
|
// error happens before or after the serializer hits a transferrable object)
|
|
|
|
final data1 = transferableFirst.materialize().asUint8List();
|
|
Expect.equals(x.lengthInBytes, data1.length);
|
|
for (int i = 0; i < data1.length; i++) {
|
|
Expect.equals(i, data1[i]);
|
|
}
|
|
}
|
|
|
|
{
|
|
final transferableSecond = TransferableTypedData.fromList([x]);
|
|
Expect.throwsArgumentError(
|
|
() => port.sendPort.send(<dynamic>[socket, transferableSecond]));
|
|
// Once TransferableTypedData was sent even if attempt failed, it can't be
|
|
// materialized.
|
|
final data2 = transferableSecond.materialize().asUint8List();
|
|
Expect.equals(x.lengthInBytes, data2.length);
|
|
for (int i = 0; i < data2.length; i++) {
|
|
Expect.equals(i, data2[i]);
|
|
}
|
|
}
|
|
|
|
{
|
|
final transferableSecond = TransferableTypedData.fromList([x]);
|
|
Expect.throwsArgumentError(() => port.sendPort
|
|
.send(<dynamic>[socket, transferableSecond, transferableSecond]));
|
|
// Once TransferableTypedData was sent even if attempt failed, it can't be
|
|
// materialized.
|
|
final data2 = transferableSecond.materialize().asUint8List();
|
|
Expect.equals(x.lengthInBytes, data2.length);
|
|
for (int i = 0; i < data2.length; i++) {
|
|
Expect.equals(i, data2[i]);
|
|
}
|
|
}
|
|
|
|
socket.close();
|
|
port.close();
|
|
}
|