Communication Channel


Tasklets (represented by future values) created from mt::start, asynchronous function ca
ll and the methods of asynchronous object  can be assigned to native threads to run concu
rrently. Tasklets can communicate and synchronize with each other using  communication 

The Channel type is implemented as a customized C data type that supports template-like t
ype arguments. So to construct a channel that  can send and receive integers, one can use
   1  var chan = mt::Channel<int>()
Here Channel is prefixed with mt::, because Channel is defined in the built-in mt multi-t
hreading module.

The type argument int indicates this channel can only be used to transmit integers. Curre
ntly, only primitive types  (int, float, double,  complex, string, enum)  plus array type
s, and their composition through  list, map and tuple  types are supported for channels. 

Each channel has a capacity for transmitting data, which are buffered in the channel.  Wh
en the channel's buffer reached its capacity, any attempt to send data to it  will result
in the blocking of the sender, which will be resumed either after  a timeout or after som
e data of the channel have been read out of the buffer  to make room for the new data bei
ng sent by the blocked sender.  Channel capacity can be passed to the constructor of the 
channel as  an optional parameter, which is one by default.

The channel type has a number of methods which include: 
  *  buffer( self: Channel<@V> ) => int
     It returns the number of unprocessed data items in the channel buffer. 
  *  cap( self: Channel<@V> ) => int
     Return the channel capacity. 
  *  cap( self: Channel<@V>, cap: int ) => int
     Set the channel capacity and returns the previous one. Set the capacity to zero to p
     revent it from receiving further data, and effectively close it when its buffer beco
     me empty. 
  *  send( self: Channel<@V>, data: @V, timeout: float = -1 ) => int
     Send a data item with a timeout. A negative timeout parameter means infinite waiting
     . It return 1 upon timeout, 0 otherwise. 
  *  receive( self: Channel<@V>, timeout: float = -1 ) => tuple<data: @V|none, status: 
     Receive a data item with a timeout. A negative timeout parameter means infinite wait
     ing. It returns a tuple with the following possible values:  
       *  (data, $received);
       *  (none, $timeout);
       *  (none, $finished);  

Here is a simple example, where integers are sent through one channel and strings through
another, and these integers and strings are received using the select method: 
   1  load sys
   3  var chans = { mt::Channel<int>(1), mt::Channel<string>(1) }
   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  }
  22  while( 1 ){
  23      var data = mt::select( chans, 0.2 )
  24      io.writeln( "received:", data );
  25      if( data.status == $finished ) break
  26  }