std.task

タスクとチャネル。async も await も無く、どの関数も上から順に読める。 task f() で別の流れとして走らせ、parallel { } でまとめて待つ。 task・parallel・channel を使うだけなら import は省ける。

func slow() -> int { sleep(0.05); return 42; }
var t = task slow();
print("先に進める");
print(t.wait());   // 42
task.yield task.count task.channel Task.wait Task.wait_timeout Task.done Task.cancel Task.id channel.send channel.recv channel.try_recv channel.close channel.len

関数

task.yield() → void

待ちが無くても、ほかのタスクに順番を譲る。

長い計算を回すタスクは、ときどき呼ぶと全体が詰まらない。

func heavy() -> int {
  var sum = 0;
  for var i in range(1000) { sum = sum + i; task.yield(); }
  return sum;
}
var t = task heavy();
print(t.wait());   // 499500
task.count() → int

いま走っているタスクの数。

print(task.count() >= 0);   // true
task.channel<T>() → channel<T>

値を受け渡す待ち行列を作る。

オーバーロード: task.channel<T>(capacity: int) -> channel<T>

var ch = channel<int>(4);
_ = ch.send(1);
print(ch.recv() ?? -1);   // 1

Task<T>

task f() が返す値。T は f の戻り値の型。

Task.wait() → T

終わるまで待って、戻り値を受け取る。

func slow() -> int { sleep(0.05); return 42; }
var t = task slow();
print(t.wait());   // 42
Task.wait_timeout(t: Duration) → T?

時間を区切って待つ。間に合わなければ none。

import std.time;
func slow() -> int { sleep(1.0); return 42; }
var t = task slow();
print(t.wait_timeout(time.seconds(0.05)) ?? -1);   // -1(間に合わない)
t.cancel();
Task.done() → bool

終わっているか。待たない。

func slow() -> int { sleep(0.05); return 1; }
var t = task slow();
while !t.done() { sleep(0.01); }
print(t.done());   // true
Task.cancel() → void

取り消しを頼む。すぐには止まらず、待っている関数が次に見たときに終わる。

func slow() -> int { sleep(1.0); return 1; }
var t = task slow();
t.cancel();
print("取り消しを頼んだ");
Task.id() → int

見分けるための番号。

func slow() -> int { return 1; }
var t = task slow();
print(t.id() >= 0);   // true

channel<T>

タスクの間で値を受け渡す待ち行列。

送り手は何個でもよく、受け取るのは1つのタスク。コピーしても同じ待ち行列を指す。

channel.send(v: T) → Result<void>

送る。ためられないときは、空くまで待つ。

var ch = channel<int>(2);
print(ch.send(1).ok());   // true
channel.recv() → T?

受け取る。何も無ければ届くまで待つ。閉じられていれば none。

func producer(ch: channel<int>) {
  for var i in range(3) { _ = ch.send(i); }
  ch.close();
}
var ch = channel<int>(4);
task producer(ch);
while var v = ch.recv() { write(v); }   // 012
print("");
channel.try_recv() → T?

待たずに受け取る。何も無ければ none。

var ch = channel<int>(2);
print(ch.try_recv() ?? -1);   // -1(まだ何も無い)
_ = ch.send(7);
print(ch.try_recv() ?? -1);   // 7
channel.close() → void

閉じる。待っている受け手には none が返る。

var ch = channel<int>(1);
ch.close();
print(ch.recv() ?? -1);   // -1
channel.len() → int

たまっている件数。

var ch = channel<int>(4);
_ = ch.send(1);
_ = ch.send(2);
print(ch.len());   // 2