Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request : Simplify Communication between Isolates in Dart with Channels #52155

Closed
sanathusk opened this issue Apr 24, 2023 · 4 comments
Closed
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-isolate type-enhancement A request for a change that isn't a bug

Comments

@sanathusk
Copy link

Proposal: Simplify Communication between Isolates in Dart with Channels

Problem
The current communication mechanism between isolates in Dart involves messages, ReceivePort, and SendPort. These terms can be confusing, and the process of setting up communication between isolates can be complicated.

Proposed Solution

Introduce a Channel structure, similar to the Go language, which simplifies the communication between isolates. A Channel would provide a more intuitive abstraction, making it easier for developers to work with isolates in Dart.

Example
Here's an example of how the Channel structure could be used in Dart:

  // Create a channel for communication between isolates
  final channel = UniChannel<String>();

  // Spawn a new isolate using SpawnWithChannel the channel's SendPort
  Isolate.spawnWithChannel(isolateFunction, channel);

  // Send a message through the channel
  await for (final value in channel) {
    print('Isolate received value: $value');
  }
}

// Isolate function
void isolateFunction(Channel<string> c) {
  // Receive and process the message
   for(int i =0;i<100;i++)
{
   c.send(sum) ;
}
} 

Benefits
- Simplifies the communication setup between isolates.
- Provides a more intuitive abstraction for developers.
- Makes it easier to manage and close communication channels.

Conclusion

Introducing a Channel structure for communication between isolates in Dart would simplify the process and provide a more intuitive abstraction for developers. This change would make it easier for developers to work with isolates and manage communication channels in their applications.

@lrhn lrhn transferred this issue from dart-lang/language Apr 24, 2023
@abitofevrything
Copy link
Contributor

You could implement this as a separate package - I don't really see how this is important enough to warrant an entry in the SDK.

Most Isolate use cases would probably need to associate the "request" with the "response" which this doesn't offer, so it's only really useful for dispatching work to another isolate, waiting asynchronously for that isolate to do the work and then resuming - which is exactly what Isolate.run does, but in a persistent isolate instead of spawning a new one every time.

@devoncarew devoncarew added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. type-enhancement A request for a change that isn't a bug labels Apr 24, 2023
@devoncarew
Copy link
Member

cc @lrhn and @mkustermann

@lrhn
Copy link
Member

lrhn commented Apr 24, 2023

Not sure how much this differs from a ReceivePort, other than being typed.

Not unless there is some implicit closing involved, say when the isolate you send it to is closed.
That's also dangerous.

But compare the code above to:

  // Create a channel for communication between isolates
  final channel = TypedReceivePort<String>();

  // Spawn a new isolate using SpawnWithChannel the channel's SendPort
  Isolate.spawn(isolateFunction, channel.sendPort);

  // Send a message through the channel
  await for (final value in channel) {
    print('Isolate received value: $value');
  }

// ...

// Isolate function.
void isolateFunction(TypedSendPort<String> c) {
  // Receive and process the message
   for(int i =0; i < 100; i++) {
     c.send(sum) ;
  }
  c.close();
} 

where we just define typed wrappers around ReceivePort and SendPort.

class TypedReceivePort<T> extends Stream<T> {
  final ReceivePort _port = RawReceivePort();
  void cancel() {
    _port.cancel();
  }
  StreamSubscription<T> listen(void Function(T)? onData, {Function? onError, void Function()? onDone, bool cancelOnError = false) {
    return _port.cast<T>.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }
  TypedSendPort<T> get sendPort => TypedSendPort<T>(_port.sendPort);
}
class TypedSendPort<T> {
  final SendPort _port;
  TypedSendPort(this._port);
  void send(T value) {
    _port.send(value);
  }
}

I'd rather make an abstraction over sending a stream, say:

class Isolate {
  // ...
  static Stream<T> runStream<T>(Stream<T> Function() computation) { ... }
}

which works like Isolate.run, but returns a stream at both ends, and forwards events and pushback between the isolates.

(My biggest conundrum around that is whether to forward pause/cancel events or use Isolate.pause/Isolate.kill instead.)

@mkustermann
Copy link
Member

mkustermann commented May 26, 2023

In Go channels are somewhat symmetric: The channel can be passed around to any go routine. Any go routine can perform blocking writes / reads.

In Dart we have an inherent asymmetry built in:

  • The created ReceivePort belongs to an isolate, it cannot be passed around to other isolates, other isolates cannot listen on it. The isolate will get notified asynchronously once events arrive.
  • The corresponding SendPort can be arbitrarily passed around across isolates. Any isolate can send messages.

This asymmetry naturally will lead to different interfaces for the receiver than the sender.

As @lrhn points out we have basically what the original feature request asks for with exception of need for typed wrappers.

We have an open issue to provide more convenient abstractions on top of isolates, see #48579. Let me expand that with the suggestion here and close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-isolate type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

5 participants