Introduction to the

Dart: I’ve seen a lot of asynchronous programming techniques in DART, but I don’t know if you’ve noticed a problem. If you’re writing asynchronous programming in Java, locking and concurrency are mentioned, but dart doesn’t seem to hear about multithreading and concurrency.

Today, I’m going to explain the isolation mechanism in DART so that you can understand.

Isolation mechanisms in DART

Dart is a single-threaded language, but as a single-threaded language, Dart supports asynchronous features like Future and Stream. This is all a result of isolation mechanisms and event loops.

First, take a look at the isolation mechanism in DART.

Isolation refers to a specific space where DART runs, with separate memory and single-threaded event loops.

As shown below:

In other languages such as Java or c++, multiple threads share memory space, which makes concurrency and data communication easy, but also makes concurrent programming difficult.

Because we need to consider the synchronization of data between multiple threads, there are many additional locking mechanisms, which should be very annoying for those who understand it in detail or have used it.

The biggest defect of multithreading is that it requires programmers to have excellent logic thinking and programming skills, so that they can design perfect multithreading programs.

But in DART, none of this is a problem. All threads in DART have their own run space, and that thread’s job is to run the event loop.

So the problem is that the main thread is handling the event loop, but what if you encounter a very time-consuming operation? Running directly on the main thread can cause the main thread to block.

Dart takes this into account, so it provides a Isolate class to manage isolation.

Because the DART program itself runs within an Isolate, if you define an Isolate within DART, that Isolate usually represents another Isolate that needs to communicate with the current Isolate.

Make an Isolate

So how do you generate an Isolate in your current DART program?

Isolate provides three generation methods.

A very common one is the Isolate’s factory method spawn:

external static Future<Isolate> spawn<T>( void entryPoint(T message), T message, {bool paused = false, bool errorsAreFatal = true, SendPort? onExit, SendPort? OnError, @ Since (" 2.3 ") String? debugName});Copy the code

Spawn creates a new Isolate and calls it with several parameters:

EntryPoint represents a function that needs to be called when a new Isolate is generated. EntryPoint takes a message argument. Generally, Message is a SendPort object used for communication between two isolates.

Paused means whether the newly generated Isolate is paused or not. Paused is equivalent to:

isolate.pause(isolate.pauseCapability)
Copy the code

If you later need to unpause the state, you can call:

isolate.resume(isolate.pauseCapability)
Copy the code

ErrorsAreFatal corresponds to the setErrorsFatal method.

OnExit corresponds to addOnExitListener and onError corresponds to addErrorListener.

DebugName indicates the name displayed during debugging of the Isolate.

If spawn fails, an IsolateSpawnException is thrown:

class IsolateSpawnException implements Exception {
  /// Error message reported by the spawn operation.
  final String message;
  @pragma("vm:entry-point")
  IsolateSpawnException(this.message);
  String toString() => "IsolateSpawnException: $message";
}
Copy the code

The spawn method generates the same Isolate as the current code. If you want to generate using a different code, you can use spawnUri to generate a different code by passing in the corresponding Uri address.

external static Future<Isolate> spawnUri( Uri uri, List<String> args, var message, {bool paused = false, SendPort? onExit, SendPort? onError, bool errorsAreFatal = true, bool? checked, Map<String, String>? environment, @Deprecated('The packages/ dir is not supported in Dart 2') Uri? packageRoot, Uri? PackageConfig, bool automaticPackageResolution = false, @ Since (" 2.3 ") String? debugName});Copy the code

Another way is to use the Isolate’s constructor:

Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability});
Copy the code

The first parameter is controlPort, which represents the control of another Isolate. The two capabilities are a subset of the original Isolate, which indicates whether pause or Terminate rights are available.

Common usage is as follows:

Isolate isolate = findSomeIsolate();
Isolate restrictedIsolate = Isolate(isolate.controlPort);
untrustedCode(restrictedIsolate);
Copy the code

Interaction between Isolate

All DART code runs within the Isolate, and code can only access classes and values within the same Isolate. Communication between isolates can be implemented using ReceivePort and SendPort.

Take a look at SendPort, which is a Capability:

abstract class SendPort implements Capability 
Copy the code

SendPort is used to send a message to ReceivePort. There are many types of message, including:

Null, Boolean, int, double, String, List, Map, TransferableTypedData, SendPort and Capability.

Note that the send action is done immediately.

In fact, SendPort is created by ReceivePort. A ReceivePort can receive multiple SendPorts.

ReceivePort is a type of Stream:

abstract class ReceivePort implements Stream<dynamic>
Copy the code

As a Stream, it provides a Listen to handle incoming messages:

StreamSubscription<dynamic> listen(void onData(var message)? , {Function? onError, void onDone()? , bool? cancelOnError});Copy the code

A case in point

After all these principles, some students may ask, how do you use them?

Here’s an example:

import 'dart:isolate'; var isolate; void entryPoint(SendPort sendPort) { int counter = 0; sendPort.send("counter:$counter"); } void main() async{ final receiver = ReceivePort(); Receiver. Listen ((message) {print(" Receive message $message"); }); isolate = await Isolate.spawn(entryPoint, receiver.sendPort); }Copy the code

On the main thread, we create a ReceivePort and call its Listen method to listen for messages from sendPort.

Spawn then generates a new Isolate, which, after initialization, calls the entryPoint method.

SendPort is also used in this entryPoint method to send a message to ReceivePort.

Final run, print:

Message counter:0 was receivedCopy the code

conclusion

So that’s the isolation mechanism in DART and the use of Isolate.

This article is available at www.flydean.com/25-dart-iso…

The most popular interpretation, the most profound dry goods, the most concise tutorial, many tips you didn’t know waiting for you to discover!

Welcome to pay attention to my public number: “procedures those things”, understand technology, more understand you!