Js_Randezvous v0.2

最初に目指していた小さなコードという目標はもはや実現できそうにないJs_Randezvousですが、意外とRandezvousモデルってJavaScriptと相性がいい気がします。ブラウザ上のJavaScriptはとにかくイベントドリブンなので、順番待ちや処理の自動選択、タイムアウトが簡単に書けるのが好印象です。

以前のバージョンから機能が増えて、selective_acceptのgurdsとterminateも実装しました。さらにJSDeferredのchild deferred的な機能としてredirectを追加しました。JSDeferredだとreturn call(pow, 2, 10)のように書きますが、Js_Randezvousではcallを別の用途で使ってしまっているので、混乱を避けるためにredirectで同じ機能を提供しています。

残りはabortとselect delay or abortぐらいでしょうか。実装の目処は何となく立っているので近いうちに何とか出来ると思います。entry familyはおそらくJavaScriptでは必要ないと思うので、実装しない予定です。

ついでに2つほどデモを追加してみました。実装しながら作った物なので、あとで綺麗にまとめ直します。

Task内でもTaskを作ることが出来るので、並行処理も楽ちんです。親側で単純にcall()すればランデブーできます。

$(function() {
      var parent = new Task(
          function() {
              this.neet = new Task(
                  function() {
                      print(2, "I'm playing for 10 secs.");
                      this.i = 0;
                  },
                  loop(function() {return this.i < 10;},
                       function() {
                           print(2, "playing...");
                           this.i++;
                       },
                       delay(1000)
                  ),
                  accept("real"),
                  function() {
                      print(2, "I want to die.");
                  }
              );
              this.neet.activate();
              print(1, "I'm wating for this.neet to accept 'real'.");
          },
          call(
              function() {return this.neet.real;}
          ),
          function() {
              print(1, "Oops.");
          }
      );
      parent.activate();
});

gurd付きselectを使ってスタックをタスクで実装した例。エントリ呼び出しはキューイングされるので、スタックが空の状態でpopを何回か押すとそのあとにpushしてもすぐに消化されます。

$(function() {
      stackTask = new Task(
          function() {
              this.stack = [];
              print(1, "[" + this.stack.join(", ") + "]");
          },
          loop(
              function() {return true;},
              select(
                  when(function() {return this.stack.length > 0;})
                      .accept("pop", function() {
                                  return this.stack.pop();
                              }),
                  accept("push", function(item) {
                             this.stack.push(item);
                         })
              ),
              function() {
                  print(1, "[" + this.stack.join(", ") + "]");
              }
          )
      );
      stackTask.activate();

      $("#stack_push").click(
          function() {stackTask.push([$("#stack_value").val()]);}
      );

      $("#stack_pop").click(stackTask.pop);
});