Unverified Commit fc3571ef authored by Martin Kustermann's avatar Martin Kustermann Committed by GitHub

Improve documentation of `compute()` function (#116878)

This improves the documentation of the `compute()` function as follows:

  * Instead of making `compute` a top-level constant, we make it a
    function. This allows the generated API docs to show a function
    signature with parameters and their names, making it *much* clearer
    to users what function is being documented.

  * We mention that on web-backends this is running `compute()` on the
    normal eventloop whereas on on native platforms it runs in a
    separate isolate.

  * We mention that callback, message and result have to be sendable
    across isolates. We also mention that they may be copied.

  * We link to both `Isolate.run` & `SendPort.send` for more information.

  * We use `M` for the type of `message` instead the rather confusing
    `Q`.
parent dcd2170d
...@@ -11,7 +11,8 @@ import 'isolates.dart' as isolates; ...@@ -11,7 +11,8 @@ import 'isolates.dart' as isolates;
export 'isolates.dart' show ComputeCallback; export 'isolates.dart' show ComputeCallback;
/// The dart:io implementation of [isolate.compute]. /// The dart:io implementation of [isolate.compute].
Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, {String? debugLabel}) async { @pragma('vm:prefer-inline')
Future<R> compute<M, R>(isolates.ComputeCallback<M, R> callback, M message, {String? debugLabel}) async {
debugLabel ??= kReleaseMode ? 'compute' : callback.toString(); debugLabel ??= kReleaseMode ? 'compute' : callback.toString();
return Isolate.run<R>(() { return Isolate.run<R>(() {
......
...@@ -7,7 +7,8 @@ import 'isolates.dart' as isolates; ...@@ -7,7 +7,8 @@ import 'isolates.dart' as isolates;
export 'isolates.dart' show ComputeCallback; export 'isolates.dart' show ComputeCallback;
/// The dart:html implementation of [isolate.compute]. /// The dart:html implementation of [isolate.compute].
Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { String? debugLabel }) async { @pragma('dart2js:tryInline')
Future<R> compute<M, R>(isolates.ComputeCallback<M, R> callback, M message, { String? debugLabel }) async {
// To avoid blocking the UI immediately for an expensive function call, we // To avoid blocking the UI immediately for an expensive function call, we
// pump a single frame to allow the framework to complete the current set // pump a single frame to allow the framework to complete the current set
// of work. // of work.
......
...@@ -9,33 +9,17 @@ import '_isolates_io.dart' ...@@ -9,33 +9,17 @@ import '_isolates_io.dart'
/// Signature for the callback passed to [compute]. /// Signature for the callback passed to [compute].
/// ///
/// {@macro flutter.foundation.compute.types}
///
/// Instances of [ComputeCallback] must be functions that can be sent to an
/// isolate.
/// {@macro flutter.foundation.compute.callback} /// {@macro flutter.foundation.compute.callback}
/// ///
/// {@macro flutter.foundation.compute.types} typedef ComputeCallback<M, R> = FutureOr<R> Function(M message);
typedef ComputeCallback<Q, R> = FutureOr<R> Function(Q message);
/// The signature of [compute], which spawns an isolate, runs `callback` on /// The signature of [compute], which spawns an isolate, runs `callback` on
/// that isolate, passes it `message`, and (eventually) returns the value /// that isolate, passes it `message`, and (eventually) returns the value
/// returned by `callback`. /// returned by `callback`.
/// typedef ComputeImpl = Future<R> Function<M, R>(ComputeCallback<M, R> callback, M message, { String? debugLabel });
/// {@macro flutter.foundation.compute.usecase}
///
/// The function used as `callback` must be one that can be sent to an isolate.
/// {@macro flutter.foundation.compute.callback}
///
/// {@macro flutter.foundation.compute.types}
///
/// The `debugLabel` argument can be specified to provide a name to add to the
/// [Timeline]. This is useful when profiling an application.
typedef ComputeImpl = Future<R> Function<Q, R>(ComputeCallback<Q, R> callback, Q message, { String? debugLabel });
/// A function that spawns an isolate and runs the provided `callback` on that /// Asynchronously runs the given [callback] - with the provided [message] -
/// isolate, passes it the provided `message`, and (eventually) returns the /// in the background and completes with the result.
/// value returned by `callback`.
/// ///
/// {@template flutter.foundation.compute.usecase} /// {@template flutter.foundation.compute.usecase}
/// This is useful for operations that take longer than a few milliseconds, and /// This is useful for operations that take longer than a few milliseconds, and
...@@ -68,34 +52,26 @@ typedef ComputeImpl = Future<R> Function<Q, R>(ComputeCallback<Q, R> callback, Q ...@@ -68,34 +52,26 @@ typedef ComputeImpl = Future<R> Function<Q, R>(ComputeCallback<Q, R> callback, Q
/// ``` /// ```
/// {@end-tool} /// {@end-tool}
/// ///
/// The function used as `callback` must be one that can be sent to an isolate. /// On web platforms this will run [callback] on the current eventloop.
/// {@template flutter.foundation.compute.callback} /// On native platforms this will run [callback] in a separate isolate.
/// Qualifying functions include:
///
/// * top-level functions
/// * static methods
/// * closures that only capture objects that can be sent to an isolate
/// ///
/// Using closures must be done with care. Due to /// {@template flutter.foundation.compute.callback}
/// [dart-lang/sdk#36983](https://github.com/dart-lang/sdk/issues/36983) a
/// closure may capture objects that, while not directly used in the closure
/// itself, may prevent it from being sent to an isolate.
/// {@endtemplate}
///
/// {@template flutter.foundation.compute.types}
/// The [compute] method accepts the following parameters:
/// ///
/// * `Q` is the type of the message that kicks off the computation. /// The `callback`, the `message` given to it as well as the result have to be
/// * `R` is the type of the value returned. /// objects that can be sent across isolates (as they may be transitively copied
/// if needed). The majority of objects can be sent across isolates.
/// ///
/// There are limitations on the values that can be sent and received to and /// See [SendPort.send] for more information about exceptions as well as a note
/// from isolates. These limitations constrain the values of `Q` and `R` that /// of warning about sending closures, which can capture more state than needed.
/// are possible. See the discussion at [SendPort.send].
/// ///
/// The same limitations apply to any errors generated by the computation.
/// {@endtemplate} /// {@endtemplate}
/// ///
/// See also: /// On native platforms `await compute(fun, message)` is equivalent to
/// `await Isolate.run(() => fun(message))`. See also [Isolate.run].
/// ///
/// * [ComputeImpl], for the [compute] function's signature. /// The `debugLabel` - if provided - is used as name for the isolate that
const ComputeImpl compute = isolates.compute; /// executes `callback`. [Timeline] events produced by that isolate will have
/// the name associated with them. This is useful when profiling an application.
Future<R> compute<M, R>(ComputeCallback<M, R> callback, M message, {String? debugLabel}) {
return isolates.compute<M, R>(callback, message, debugLabel: debugLabel);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment