diff --git a/lib/ui/isolate_name_server.dart b/lib/ui/isolate_name_server.dart index 4c1833bc52646eef06603bb4090795defe31c9c3..59d85877a1acd335689e6b0cdab533cf594a3765 100644 --- a/lib/ui/isolate_name_server.dart +++ b/lib/ui/isolate_name_server.dart @@ -4,31 +4,67 @@ part of dart.ui; -/// Contains methods to allow for simple sharing of SendPorts across isolates. -abstract class IsolateNameServer { - /// Looks up the [SendPort] associated with a given name. Returns null - /// if the name does not exist. +/// Static methods to allow for simple sharing of [SendPort]s across [Isolate]s. +/// +/// All isolates share a global mapping of names to ports. An isolate can +/// register a [SendPort] with a given name using [registerPortWithName]; +/// another isolate can then look up that port using [lookupPortByName]. +/// +/// To create a [SendPort], first create a [ReceivePort], then use +/// [ReceivePort.sendPort]. +/// +/// Since multiple isolates can each obtain the same [SendPort] associated with +/// a particular [ReceivePort], the protocol built on top of this mechanism +/// should typically consist of a single message. If more elaborate two-way +/// communication or multiple-message communication is necessary, it is +/// recommended to establish a separate communication channel in that first +/// message (e.g. by passing a dedicated [SendPort]). +class IsolateNameServer { + // This class is only a namespace, and should not be instantiated or + // extended directly. + factory IsolateNameServer._() => null; + + /// Looks up the [SendPort] associated with a given name. + /// + /// Returns null if the name does not exist. To register the name in the first + /// place, consider [registerPortWithName]. /// - /// `name` must not be null. + /// The `name` argument must not be null. static SendPort lookupPortByName(String name) { assert(name != null, "'name' cannot be null."); return _lookupPortByName(name); } - /// Registers a SendPort with a given name. Returns true if registration is - /// successful, false if the name entry already exists. + /// Registers a [SendPort] with a given name. + /// + /// Returns true if registration is successful, and false if the name entry + /// already existed (in which case the earlier registration is left + /// unchanged). To remove a registration, consider [removePortNameMapping]. + /// + /// Once a port has been registered with a name, it can be obtained from any + /// [Isolate] using [lookupPortByName]. /// - /// `port` and `name` must not be null. + /// Multiple isolates should avoid attempting to register ports with the same + /// name, as there is an inherent race condition in doing so. + /// + /// The `port` and `name` arguments must not be null. static bool registerPortWithName(SendPort port, String name) { assert(port != null, "'port' cannot be null."); assert(name != null, "'name' cannot be null."); return _registerPortWithName(port, name); } - /// Removes a name to SendPort mapping given a name. Returns true if the - /// mapping was successfully removed, false if the mapping does not exist. + /// Removes a name-to-[SendPort] mapping given its name. + /// + /// Returns true if the mapping was successfully removed, false if the mapping + /// did not exist. To add a registration, consider [registerPortWithName]. + /// + /// Generally, removing a port name mapping is an inherently racy operation + /// (another isolate could have obtained the name just prior to the name being + /// removed, and thus would still be able to communicate over the port even + /// after it has been removed). /// - /// `name` must not be null. + /// The `name` argument must not be null. static bool removePortNameMapping(String name) { assert(name != null, "'name' cannot be null."); return _removePortNameMapping(name); diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart index c4811187cf98beb814d4f5634f97427eaedec10e..9b6b680d0d6872cf1e6ac1eb28d0065eea37ee11 100644 --- a/lib/ui/painting.dart +++ b/lib/ui/painting.dart @@ -1522,10 +1522,10 @@ class _ImageInfo { /// [Canvas.drawImage]. @pragma('vm:entry-point') class Image extends NativeFieldWrapperClass2 { - /// This class is created by the engine, and should not be instantiated - /// or extended directly. - /// - /// To obtain an [Image] object, use [instantiateImageCodec]. + // This class is created by the engine, and should not be instantiated + // or extended directly. + // + // To obtain an [Image] object, use [instantiateImageCodec]. @pragma('vm:entry-point') Image._(); @@ -1587,13 +1587,20 @@ class FrameInfo extends NativeFieldWrapperClass2 { } /// A handle to an image codec. +/// +/// This class is created by the engine, and should not be instantiated +/// or extended directly. +/// +/// To obtain an instance of the [Codec] interface, see +/// [instantiateImageCodec]. @pragma('vm:entry-point') class Codec extends NativeFieldWrapperClass2 { - /// This class is created by the engine, and should not be instantiated - /// or extended directly. - /// - /// To obtain an instance of the [Codec] interface, see - /// [instantiateImageCodec]. + // + // This class is created by the engine, and should not be instantiated + // or extended directly. + // + // To obtain an instance of the [Codec] interface, see + // [instantiateImageCodec]. @pragma('vm:entry-point') Codec._(); @@ -1656,8 +1663,8 @@ String _instantiateImageCodec(Uint8List list, _Callback callback, _ImageI /// Loads a single image frame from a byte array into an [Image] object. /// -/// This is a convenience wrapper around [instantiateImageCodec]. -/// Prefer using [instantiateImageCodec] which also supports multi frame images. +/// This is a convenience wrapper around [instantiateImageCodec]. Prefer using +/// [instantiateImageCodec] which also supports multi frame images. void decodeImageFromList(Uint8List list, ImageDecoderCallback callback) { _decodeImageFromListAsync(list, callback); } diff --git a/lib/ui/plugins.dart b/lib/ui/plugins.dart index a0c65461a3e7a826741c3c1cecb4855aa3e3c0d5..816b99aa17bc4253126c6f2a4eb8908ea3c885bf 100644 --- a/lib/ui/plugins.dart +++ b/lib/ui/plugins.dart @@ -4,10 +4,10 @@ part of dart.ui; -/// An wrapper for a raw callback handle. +/// A wrapper for a raw callback handle. +/// +/// This is the return type for [PluginUtilities.getCallbackHandle]. class CallbackHandle { - final int _handle; - /// Create an instance using a raw callback handle. /// /// Only values produced by a call to [CallbackHandle.toRawHandle] should be @@ -15,20 +15,31 @@ class CallbackHandle { CallbackHandle.fromRawHandle(this._handle) : assert(_handle != null, "'_handle' must not be null."); - /// Get the raw callback handle to pass over a [MethodChannel] or isolate - /// port. + final int _handle; + + /// Get the raw callback handle to pass over a [MethodChannel] or [SendPort] + /// (to pass to another [Isolate]). int toRawHandle() => _handle; @override - int get hashCode => _handle; + bool operator ==(dynamic other) { + if (runtimeType != other.runtimeType) + return false; + final CallbackHandle typedOther = other; + return _handle == typedOther._handle; + } @override - bool operator ==(dynamic other) => - (other is CallbackHandle) && (_handle == other._handle); + int get hashCode => _handle.hashCode; } /// Functionality for Flutter plugin authors. -abstract class PluginUtilities { +/// +/// See also: +/// +/// * [IsolateNameServer], which provides utilities for dealing with +/// [Isolate]s. +class PluginUtilities { // This class is only a namespace, and should not be instantiated or // extended directly. factory PluginUtilities._() => null; @@ -41,7 +52,7 @@ abstract class PluginUtilities { /// Get a handle to a named top-level or static callback function which can /// be easily passed between isolates. /// - /// `callback` must not be null. + /// The `callback` argument must not be null. /// /// Returns a [CallbackHandle] that can be provided to /// [PluginUtilities.getCallbackFromHandle] to retrieve a tear-off of the @@ -58,7 +69,7 @@ abstract class PluginUtilities { /// Get a tear-off of a named top-level or static callback represented by a /// handle. /// - /// `handle` must not be null. + /// The `handle` argument must not be null. /// /// If `handle` is not a valid handle returned by /// [PluginUtilities.getCallbackHandle], null is returned. Otherwise, a