When I found out that Google Dart supports Isolates (which is some kind of multithreading for Dart, if have not heard it yet) I was excited. Still Isolates are among my favorites. But the first version of the API was pretty complex. It reminded heavily on Java Threading and honestly it was pretty difficult to get into it. But the Dart developers said pretty early that they want to do some refactoring. They did.
In the first API version you had to create an Isolate with extending the Isolate class. You had to choose between “heavy” and “light” Isolates yourself. This all is history with the new Isolates API. The Dart VM decides for you if it needs heavy or light Isolates (or if it can work with it). Also you don’t need to extend a class for Isolates anymore, you work with Functions. The result is a much more readable code. Here is an example.
First you need to import the Isolate package. This is new. Before you had the Isolate classes in the core.
First I will define a function (!) which shall act as a new Isolate.
This function is a top level function and does not have a return type. Using “void” as return type will break your code by the way. On the second line you see that I am accessing “port”. Actually this is a get-Method which return the port of this function to me. Via a port one can communicate with other Isolates.
The port can take a function which is executed when a message is received. The arguments are the actual message, which should be a primitive value like null, num, bool, double or String. List and Maps containing these values are also allowed. Objects are allowed too, when the Isolates are running in the same process (formerly known as light Isolate). This is the case, if you spawn the new Isolate with “spawnFunction” - say the docs.
In addition to the message argument you get a SendPort, which is some kind of a backchannel to the sending Isolate.
In my function I print the message, send back a “close”-String and finally close the port. The Isolate is then ready for trash and the VM should clean it up then. Don’t forget to close your ports when you are done or it is very much likely that your code will run forever and probably cause messes around with your memory.
That’s it for the new Isolate function so far. Let’s look into how we actually spawn it.
This code runs in my main-Method. This is just another Isolate, therefore I have a port ready to access. I put a function as my receiver, which again prints the message and closes my port. Once the main Isolates port closes, the application is done.
Then I call “spawnFunction()” and my argument is the mentioned top level function. You see, I don’t use parenthesis here. The reason is that I need the reference to my function and not its result. The real execution should be done by the spawnFunction-Method - in its own Isolate.
The spawnFunction-Method returns me a SendPort which I use in the last line to send a first message. My second argument is the back channel for the second Isolate. Now I can get the replies of “process”.
That’s it already.
I have observed that a function is not spawned when the port.receive() Method didn’t get a function. In addition, don’t put a “void” to your top level function definition. Last but not least I saw this API can break when you are not sending a port or null as SendPort argument, even when it is marked as optional in the API Docs.
There is support in the SendPort if you prefer to work with Futures. It is even possible to spawn an Isolate from an Uri. You can read more at the official docs.
For me this API has progressed well - everything is easier and one needs less code. Let’s see how it looks in another couple of month. I have read somewhere about Isolates which can act on the same piece of DOM which can significantly speed up webapps. Wouldn’t it be nice?
Tags: #Dart #Open Source