| // Copyright (c) 2025, 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:async'; | |
| import 'dart:ffi'; | |
| void main() async { | |
| print( | |
| 'returnRegularFuture returns: ' | |
| '${await returnRegularFuture(5)}', | |
| ); | |
| print( | |
| 'sumIntStream(useAsyncStar = false) returns: ' | |
| '${await sumIntStream(5, 1, false)}', | |
| ); | |
| print( | |
| 'sumIntStream(useAsyncStar = true) returns: ' | |
| '${await sumIntStream(5, 1, true)}', | |
| ); | |
| } | |
| Future<int> returnRegularFuture(int delayMs) async { | |
| await Future.delayed(Duration(milliseconds: 5)); | |
| return 256; | |
| } | |
| Future<int> returnMicrotaskFuture(int delayMs) => Future.microtask(() async { | |
| await Future.delayed(Duration(milliseconds: delayMs)); | |
| return 256; | |
| }); | |
| Stream<int> produceIntStreamWithAsyncStar(int count, int delayMs) async* { | |
| final delay = Duration(milliseconds: delayMs); | |
| for (var i = 0; i < count; i++) { | |
| await Future.delayed(delay); | |
| yield i; | |
| } | |
| } | |
| Stream<int> produceIntStreamWithController(int count, int delayMs) { | |
| final delay = Duration(milliseconds: delayMs); | |
| final sc = StreamController<int>(); | |
| (() async { | |
| for (var i = 0; i < count; i++) { | |
| await Future.delayed(delay); | |
| sc.add(i); | |
| } | |
| sc.close(); | |
| })(); | |
| return sc.stream; | |
| } | |
| Future<int> sumIntStream(int count, int delayMs, bool useAsyncStar) async { | |
| final stream = useAsyncStar | |
| ? produceIntStreamWithAsyncStar(count, delayMs) | |
| : produceIntStreamWithController(count, delayMs); | |
| var sum = 0; | |
| await for (var value in stream) { | |
| sum += value; | |
| } | |
| return sum; | |
| } | |
| Future<int> awaitAndMultiply(Future<int> a, Future<int> b) async => | |
| (await a) * (await b); | |
| class AwaitAndMultiplyCall { | |
| final _a = Completer<int>(); | |
| final _b = Completer<int>(); | |
| Future<int> getA() => _a.future; | |
| Future<int> getB() => _b.future; | |
| @pragma('vm:entry-point', 'call') | |
| void setA(int value) => _a.complete(value); | |
| @pragma('vm:entry-point', 'call') | |
| void setB(int value) => _b.complete(value); | |
| } | |
| @pragma('vm:entry-point', 'call') | |
| AwaitAndMultiplyCall awaitAndMultiplyC(int callbackPtr, int contextPtr) { | |
| final call = AwaitAndMultiplyCall(); | |
| () async { | |
| Pointer<NativeFunction<Void Function(Pointer<Opaque>, Int64)>>.fromAddress( | |
| callbackPtr, | |
| ).asFunction<void Function(Pointer<Opaque>, int)>()( | |
| Pointer<Opaque>.fromAddress(contextPtr), | |
| await awaitAndMultiply(call.getA(), call.getB()), | |
| ); | |
| }(); | |
| return call; | |
| } | |
| @pragma('vm:entry-point', 'call') | |
| // C-friendly wrapper over [returnRegularFuture]. | |
| void returnRegularFutureC( | |
| int delayMs, | |
| bool useMicrotask, | |
| int callbackPtr, | |
| int contextPtr, | |
| ) async => | |
| Pointer<NativeFunction<Void Function(Pointer<Opaque>, Int64)>>.fromAddress( | |
| callbackPtr, | |
| ).asFunction<void Function(Pointer<Opaque>, int)>()( | |
| Pointer<Opaque>.fromAddress(contextPtr), | |
| await (useMicrotask | |
| ? returnMicrotaskFuture(delayMs) | |
| : returnRegularFuture(delayMs)), | |
| ); | |
| @pragma('vm:entry-point', 'call') | |
| // C-friendly wrapper over [sumIntStream]. | |
| void sumIntStreamC( | |
| int count, | |
| int delayMs, | |
| bool useAsyncStar, | |
| int callbackPtr, | |
| int contextPtr, | |
| ) async => | |
| Pointer<NativeFunction<Void Function(Pointer<Opaque>, Int64)>>.fromAddress( | |
| callbackPtr, | |
| ).asFunction<void Function(Pointer<Opaque>, int)>()( | |
| Pointer<Opaque>.fromAddress(contextPtr), | |
| await sumIntStream(count, delayMs, useAsyncStar), | |
| ); |