Files
sdk/tests/lib_2/isolate/transferable_failed_to_send_test.dart
T
Alexander Aprelev 4ccae238ea [vm/isolate] Add TransferableTypedData class that allows low-cost passing of Uint8List between isolates.
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>
2019-06-06 19:49:07 +00:00

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();
}