[NAME] ALL.dao.concurrent.channel [TITLE] Communication Channel [DESCRIPTION] Tasklets (represented by future values) created from mt::start, asynchronous function call and the methods of asynchronous object can be assigned to native threads to run concurrently. Tasklets can communicate and synchronize with each other using communication channels. The channel type is implemented as a customized C data type that supports template-like type arguments. So to construct a channel that can send and receive integers, one can use, 1 chan = mt::channel<int>() Here channel is prefixed with mt::, because channel is defined in the built-in mt multi-threading module. The type argument int indicates this channel can only be used to transmit integers. Currently, only primitive types ( int, float, double, complex, string, enum) plus array types, 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. When 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 some data of the channel have been read out of the buffer to make room for the new data being 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 prevent it from receiving further data, and effectively close it when its buffer become 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 : enum<received,timeout,finished>> Receive a data item with a timeout. A negative timeout parameter means infinite waiting. It returns a tuple with the following possible values: * (data, $received); * (none, $timeout); * (none, $finished); * select( group :list<@T>, timeout = -1.0 ) => tuple<selected: none|@T, value :any, status :enum<selected,timeout,finished>> Select on a group of channels, wait with a timeout for data become available from any of the channels. It returns a tuple with the following possible values: * (channel, data, $selected); * (none, none, $timeout); * (none, none, $finished); As the signature indicates, this is a static method. 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 2 3 chans = { mt::channel<int>(1), mt::channel<string>(1) } 4 5 mt.start { 6 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 data = mt::channel::select( chans, 0.2 ) 24 io.writeln( "received:", data ); 25 if( data.status == $finished ) break 26 }