高阶协程

我们前面的例子不会被认为是好的实践,因为协程不是可重用的组件。协同程序的编程都是关于模块化的。让我们看看更好的方法:

// writer fibre
proc writer (out: %>int) ()
{
  for i in 1..10 do
    println$ "Sending " + i.str;
    write (out,i);
  done
}

// reader fibre
proc reader (inp: %<int) ()
{
  while true do
    var x = read inp;
    println$ "Read " + x.str;
  done
}

proc start_network () {
  // schannels for communication
  var inp, out = mk_ioschannel_pair[int]();
  var co_writer = writer inp;
  var co_reader = reader  out;
  spawn_fibre co_writer;
  spawn_fibre co_reader;
}

start_network;

这个程序与我们的第一个例子做的是一样的事情,但是我们通过使读写器命名为过程,并且显式地传递它们应该与之通信的通道,使它们模块化。

类型 %>intoschannel[int] ,INT的输出通道,以及 %<intischannel[int] ,ints的输入通道。因为 spawn_fibre 需要接受参数的过程 () 我们还得加上这一点。

这里的另一个重构是,我们也将网络构造代码模块化为一个过程。它创建所需的通道,将读写器过程绑定到它们需要的通道上,然后生成绑定过程来创建纤程。

然后它又回来了。这很重要!当它回来时 忘记 临时指定给频道的名称。这意味着主线,在调用 start_network ,无法到达通道。尽管通道是在构造函数中命名的,但是它们在之后被遗忘了,除了被使用它们的协程之外。我们还忘记了临时指定给绑定的协同路由的名称。

当使用协程时,忘记不需要知道的是绝对必要的,因为可达性是用来驱动终止的。我希望你注意到,即使读卡器有一个无限循环,程序仍然会终止!