Friday, January 6, 2012

More Complex Dart Isolates

‹prev | My Chain | next›

For the past few days I have been experimenting with Isolates, ReceivePort, SendPort and Futures in Dart. I think that I have my brain more or less wrapped around them. It's always the "less" that spells trouble for me.

So tonight I hope to take my Doomsday solution from yesterday and beef it up. As I found out, the 2011 doomsday falls on a Wednesday. I wonder which other years in the 21st century have Wednesday doomsdays.

To answer that question, I am going to spawn yet another isolate whose responsibility it is to spawn yesterday's Doomsday isolate to determine the doomsday of every year in the 21st century. I will the filter out everything but the Wednesdays. What could possibly go wrong?

First up, my new finder-of-doom class:
class DoomsDayFinder extends Isolate {
  main () {
    port.receive((century, replyTo) {
      this.find('Wed', century).then((wednesdays) {
        replyTo.send(wednesdays);
      });
    });
  }
}
That is not complete yet, but it does sub-class Isolate, as an isolate must. It also defines the main() method that spawn() will call when the Send/ReceivePorts are ready. Since the ports are ready, I can define the receive() callback, which will be sent the century being searched.

In the callback, I ask to find() the Wednesdays in the supplied century. Since I am defining a then() callback once all the Wednesday are found, the return value of find() needs to be a future. As I found the other day, a completer is a good mechanism for building futures:
class DoomsDayFinder extends Isolate {
  main() { /* ... */  }

  find(day, century) {
    final completer = new Completer()
        , doom = new DoomsDay()
        , matching_years = [];

    for (var i=0; i <100; i++) {
      // find wednesday doomsdays
    }

    return completer.future;
  }
}
Also in there is the DoomsDay isolate from yesterday. Inside that poor man's iteration (I do wish Dart supported ranges out of the box), I am going to spawn an isolate for each year, adding the year to the list of matching years if the day is a Wednesday. To find those Wednesdays, I try the following:
class DoomsDayFinder extends Isolate {
  main() { /* ... */ }

  find(day, century) {
    final completer = new Completer()
        , doom = new DoomsDay()
        , matching_years = [];

    for (var i=0; i <100; i++) {
      var year = century + i;
      doom.spawn().then((port) {
        port.call({'year':year}).receive((message, replyTo) {
          if (message == 'Wed') matching_years.add(year);
        });
      });
    }

    return completer.future;
  }
}
For the most part, that should work. Except.... I am not completing my future. The future being returned at the end of find() will only invoke the next step, the then() callback, if something tells the completer that it is... complete.

Sadly, I can think of no other way to accomplish this than via a tracking variable that counts the number of replies received from the various Doomsday spawn. Once the number of replies reaches 100, then find() is complete:
class DoomsDayFinder extends Isolate {
  main() { /*... */  }

  find(day, century) {
    final completer = new Completer()
        , doom = new DoomsDay()
        , matching_years = [];

    var replies = 0;

    for (var i=0; i <100; i++) {
      var year = century + i;
      doom.spawn().then((port) {
        port.call({'year':year}).receive((message, replyTo) {
          replies = replies + 1;

          if (message == 'Wed') matching_years.add(year);

          if (replies >= 100) {
            completer.complete(matching_years);
          }

        });
      });
    }

    return completer.future;
  }
}
Ew. That leaves a little to be desired, but it does work:
➜  command_line git:(master) ✗ dart isolates03.dart
[2001, 2007, 2012, 2018, 2029, 2035, 2040, 2046, 2057, 2063, 2068, 2074, 2085, 2091, 2096, ]
(try.dartlang.org)


That's a crazy amount of overhead for a simple calculation. Perhaps tomorrow I will come up with something more realistic. If nothing else, I think I am getting the hang of these beasties. And they're pretty damn fun.

Day #257

3 comments:

  1. Hey Chris, what are you using for your code formatter in your blog? It looks really nice for Dart. :)

    ReplyDelete
  2. I'm using google-code-prettyify (http://code.google.com/p/google-code-prettify/). I think it's probably just guessing that I'm writing JS because it doesn't support Dart yet.

    ReplyDelete