Skip to content

Add await to callsites of BasicMessageChannel.send#182868

Merged
auto-submit[bot] merged 17 commits intoflutter:masterfrom
victorsanni:send-awaits
Mar 3, 2026
Merged

Add await to callsites of BasicMessageChannel.send#182868
auto-submit[bot] merged 17 commits intoflutter:masterfrom
victorsanni:send-awaits

Conversation

@victorsanni
Copy link
Contributor

@victorsanni victorsanni commented Feb 24, 2026

Impl:

  /// Sends the specified [message] to the platform plugins on this channel.
  ///
  /// Returns a [Future] which completes to the received response, which may
  /// be null.
  Future<T?> send(T message) async {
    return codec.decodeMessage(await binaryMessenger.send(name, codec.encodeMessage(message)));
  }

Part of #181513

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) d: examples Sample code and demos f: routes Navigator, Router, and related APIs. labels Feb 24, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds await to callsites of BasicMessageChannel.send, which is now an async method. The changes are generally correct and necessary. However, I've found a couple of issues in the benchmark file dev/benchmarks/platform_channels_benchmarks/lib/main.dart. One change introduces a performance regression by serializing parallel operations, and another uses an async/await anti-pattern. I've provided suggestions to fix these issues.

Comment on lines 72 to 74
await basicStandard.send(payload).then((Object? result) {
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Adding await inside this loop makes it sequential, which defeats the purpose of the _runBasicStandardParallel benchmark. Each iteration now waits for the send operation to complete before starting the next, removing the parallelism.

To restore the parallel behavior, the await should be removed.

    basicStandard.send(payload).then((Object? result) {
      _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
    });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use await Future.forEach() or Future.wait instead.

Comment on lines 55 to 57
await basicStandard.send(payload).then((Object? result) {
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using await with .then() is an anti-pattern in modern Dart as it can be expressed more clearly using async/await. This also avoids creating a Future<Future<void>> which is likely not intended.

    await basicStandard.send(payload);
    _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This future should have a .catch that reports error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the current impl satisfactory?

Copy link
Contributor

@dkwingsmt dkwingsmt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally ok.

basicStandard.send(payload).then((Object? result) {
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});
await Future.wait([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future.wait is meant to run tasks in parallel and wait for the completion of all of them.

You should replace the entire for loop with something like (psuedocode):

await Future.wait(List.generate(parallel, (_) => () async {
    await basicStandard.send(payload);
    await _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
}));

await Future.wait(
Iterable.generate(parallel, (_) async {
await basicStandard.send(payload);
// ignore: unawaited_futures
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignoring because recursive method is intended to run in parallel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure we can't have await here? I think this still runs in parallel even if you use await, since Iterable.generate runs everything at the same time. In other words, each (_) async { ... } runs in parallel.

_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});
await basicStandard.send(payload);
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await (or return)

Comment on lines +50 to +75
@@ -68,11 +67,12 @@ Future<double> _runBasicStandardParallel(
final completer = Completer<int>();
final counter = _Counter();
watch.start();
for (var i = 0; i < parallel; ++i) {
basicStandard.send(payload).then((Object? result) {
_runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
});
}
await Future.wait(
Iterable.generate(parallel, (_) async {
await basicStandard.send(payload);
await _runBasicStandardParallelRecurse(basicStandard, counter, count, completer, payload);
}),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry but I just realized that we might have been doing something wrong. _runBasicStandardParallelRecurse is using its completer parameter as the async control, and shouldn't need additional Future return value.

(I suspect that this entire function is basically reinventing Future.wait from scratch.)

In short, I think the original implementation is probably completely correct and we shouldn't change it at all. It doesn't have anything that violate the lint either, right? All futures either has .then or is awaited.

Merged via the queue into flutter:master with commit 3b61844 Mar 3, 2026
73 of 74 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Mar 3, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 3, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 3, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 3, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 4, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 5, 2026
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Mar 5, 2026
Roll Flutter from 46fb7210422d to d3dd7744e81f (33 revisions)

flutter/flutter@46fb721...d3dd774

2026-03-04 [email protected] Show warning when plugins do not support SwiftPM (flutter/flutter#182506)
2026-03-04 [email protected] Give guided message when project is not compatible with SwiftPM (flutter/flutter#182394)
2026-03-04 [email protected] Pass --web-define through to web runner when using --machine mode (flutter/flutter#183228)
2026-03-04 [email protected] Improve SwiftPM minimum platform mismatch diagnostics (flutter/flutter#182375)
2026-03-04 [email protected] Use dart::bin::SetupDartIo to setup dart:io (flutter/flutter#176714)
2026-03-04 [email protected] Roll Skia from 3197848b14ad to ada0b7628c79 (5 revisions) (flutter/flutter#183221)
2026-03-04 [email protected] Roll Skia from fe9e9f22c531 to 3197848b14ad (15 revisions) (flutter/flutter#183198)
2026-03-04 [email protected] refactor: remove material in reorderable_list_test, scroll_notification_test, scroll_physics_test, shortcuts_test, sliver_floating_header_test, snapshot_widget_test (flutter/flutter#182698)
2026-03-04 [email protected] refactor: remove material in pop_scope_test, route_notification_message_test, two_dimensional_utils, two_dimensional_viewport_test (flutter/flutter#182699)
2026-03-04 [email protected] Add dev/benchmarks/README.md (flutter/flutter#182976)
2026-03-03 [email protected] Roll RapidJSON to a branch based on the current upstream head (flutter/flutter#183048)
2026-03-03 [email protected] [Impeller] Update comments to reflect new info about 2-pass rendering (flutter/flutter#183050)
2026-03-03 [email protected] Add vmservices for accessibilityEvaluation (flutter/flutter#182791)
2026-03-03 [email protected] Roll Fuchsia Linux SDK from 0dCDM2oORHwDf_pyb... to JJw5EJ87vLGqFVl4h... (flutter/flutter#183177)
2026-03-03 [email protected] Support mixed color spaces in `Color.lerp` (flutter/flutter#182934)
2026-03-03 [email protected] Add warning when there is a widget with color between `Material` and `ListTile` (flutter/flutter#181402)
2026-03-03 [email protected] [ios]uitest for admob banner in scrollable list gesture issue (flutter/flutter#183128)
2026-03-03 [email protected] Roll Packages from faa4e22 to 9083bc9 (4 revisions) (flutter/flutter#183164)
2026-03-03 [email protected] Build App and native asset frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183136)
2026-03-03 [email protected] Roll Skia from f886711f180d to fe9e9f22c531 (4 revisions) (flutter/flutter#183155)
2026-03-03 [email protected] Roll Dart SDK from e86dbe9aa742 to c597ef90d2dc (2 revisions) (flutter/flutter#183147)
2026-03-03 [email protected] fix: bump matcher (flutter/flutter#183167)
2026-03-02 [email protected] Use isA to test for exceptions (flutter/flutter#183129)
2026-03-02 [email protected] [two_dimensional_scrollables] Fix tableview janks when first row/column pinned (flutter/flutter#180563)
2026-03-02 [email protected] Add await to callsites of BasicMessageChannel.send (flutter/flutter#182868)
2026-03-02 [email protected] Roll pub packages (flutter/flutter#183133)
2026-03-02 [email protected] Improve FFI code for windowing (flutter/flutter#183098)
2026-03-02 [email protected] [workflow] Update the changelog merge action to fetch the stable branch (flutter/flutter#183132)
2026-03-02 [email protected] Roll Skia from e180358b7a7a to f886711f180d (2 revisions) (flutter/flutter#183130)
2026-03-02 [email protected] Merge changelog from 3.41.3. (flutter/flutter#183131)
2026-03-02 [email protected] Make TextDecoration final and unify maskValue across platforms (flutter/flutter#183070)
2026-03-02 [email protected] Roll pub packages (flutter/flutter#182640)
2026-03-02 [email protected] Enable SwiftPM by default on master and beta (flutter/flutter#182923)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
...
xxxOVALxxx pushed a commit to xxxOVALxxx/flutter that referenced this pull request Mar 10, 2026
Impl:

```dart
  /// Sends the specified [message] to the platform plugins on this channel.
  ///
  /// Returns a [Future] which completes to the received response, which may
  /// be null.
  Future<T?> send(T message) async {
    return codec.decodeMessage(await binaryMessenger.send(name, codec.encodeMessage(message)));
  }
```

Part of flutter#181513
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) d: examples Sample code and demos f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants