高阶协程
我们前面的例子不会被认为是好的实践,因为协程不是可重用的组件。协同程序的编程都是关于模块化的。让我们看看更好的方法:
// 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;
这个程序与我们的第一个例子做的是一样的事情,但是我们通过使读写器命名为过程,并且显式地传递它们应该与之通信的通道,使它们模块化。
类型 %>int 是 oschannel[int] ,INT的输出通道,以及 %<int 是 ischannel[int] ,ints的输入通道。因为 spawn_fibre 需要接受参数的过程 () 我们还得加上这一点。
这里的另一个重构是,我们也将网络构造代码模块化为一个过程。它创建所需的通道,将读写器过程绑定到它们需要的通道上,然后生成绑定过程来创建纤程。
然后它又回来了。这很重要!当它回来时 忘记 临时指定给频道的名称。这意味着主线,在调用 start_network ,无法到达通道。尽管通道是在构造函数中命名的,但是它们在之后被遗忘了,除了被使用它们的协程之外。我们还忘记了临时指定给绑定的协同路由的名称。
当使用协程时,忘记不需要知道的是绝对必要的,因为可达性是用来驱动终止的。我希望你注意到,即使读卡器有一个无限循环,程序仍然会终止!