[NAME]
ALL.dao.concurrent.channel

[TITLE]
通讯管道

[DESCRIPTION]

轻任务(由未来值表示)可由mt::start方法, 异步函数调用和异步对象的方法调用产生。 它们将被分配
到系统线程上并行执行。 轻任务可通过通讯管道进行通讯,同步与调度处理。

管道类型Channel被实现为一个用户定制的类型, 它可以带类似模版类型的类型参数。因此,要创建一个
可发送和接收 整数的管道,可用下面的方式: 
     
   1  var chan = mt::Channel<int>()
     
这里Channel带了前缀mt::, 因为Channel是多线程模块mt里定义的一个类型。

这个管道类型的类型参数为int表示这个管道只能用来传输整数。 目前仅基本类型如intfloatdoublecomplexstringenum, 数值数组类型以及这类型通过listmaptuple 构成的复合类型才可用作管道
类型的类型参数。

每个管道对象都有个数据传输容量,它决定了管道里能缓存的消息个数。 当它缓存的消息个数达到它的
容量后,再向它发送消息将导致发送者轻任务阻塞, 直到它等足一个预先指定的时间,或有其它轻任务从
该管道里读出了消息使得 该管道的容量又变成未满的状态。 管道容量可在管道对象创建时作为参数传
递给它的初始化方法。 这方法定义的缺省管道容量为一。

管道类型有以下方法: 
  *  buffer( self: Channel<@V> ) => int
     它返回管道里未被读取的消息数目。 
  *  cap( self: Channel<@V> ) => int
     返回管道的容量。 
  *  cap( self: Channel<@V>, cap: int ) => int
     设置管道的容量,并返回原先的容量。将容量设为零将阻止它接收新的消息, 这实际上就将该管道
     关闭了。 
  *  send( self: Channel<@V>, data: @V, timeout: float = -1 ) => int
     向管道发送消息,并指定一个等待超时时间。负值超时时间表示无限时间等待。 超时后返回一,否者
     返回零。 
  *  receive( self: Channel<@V>, timeout: float = -1 ) => tuple<data: @V|none, status: 
     enum<received,timeout,finished>>
     从管道里读取消息,并指定一个等待超时时间。负值超时时间表示无限时间等待。 它可返回一个带
     以下可能值的元组:  
       *  (data, $received);
       *  (none, $timeout);
       *  (none, $finished);  
     

这里是个简单的例子: 
     
   1  load sys
   2  
   3  var chans = { mt::Channel<int>(1), mt::Channel<string>(1) }
   4  
   5  mt.start {
   6      var index = 0;
   7      while( ++index <= 10 ){
   8          if( rand(2) ){
   9              io.writeln( "sending integer:", index );
  10              chans[0].send( index )
  11          }else{
  12              io.writeln( "sending string: S" + (string) index );
  13              chans[1].send( 'S' + (string) index )
  14          }   
  15          sys.sleep(0.5)
  16      }   
  17      # set channel buffer sizes to zero to close them:
  18      chans[0].cap(0) 
  19      chans[1].cap(0)
  20  }
  21  
  22  while( 1 ){
  23      var data = mt::select( chans, 0.2 )
  24      io.writeln( "received:", data );
  25      if( data.status == $finished ) break
  26  }