    [NAME]
    ALL.dao.tutorial.concurrent

    [TITLE]
    Concurrent Programming

    [DESCRIPTION]

    Dao has several features that support concurrent programming. The first is a concurrent
    Garbage Collector (GC), which works behind the scene. The other features come in the
    following forms: multi-threading module, asynchronous function call and asynchronous
    object, which are built around a lightweight thread pool with a simple scheduler to map
    thread tasks (or tasklets) to native threads.

     0.1   Multi-threading Module

    The Multi-threading Module ( mt) offers the traditional multi-threading based on threads
    with mutexes, condition variables and semaphores. The main functionalities of mt are
    provided as code section methods for maximum flexibility and expressiveness. For example,
    a tasklet can be started with the mt.start() method,

       1  fut1 = mt.start {
       2      sum = 0;
       3      for( i = 1 : 10000 ) sum += i * i
       4      return sum
       5  }
       6  fut2 = mt.start( $now ) {
       7      sum = 0;
       8      for( i = 1 : 10000 ) sum += i * i
       9      return sum
      10  }
      11  io.writeln( fut1.value(), fut2.value() )

    mt.start() can execute any expression or block of codes as a tasklet, which may be
    scheduled to run when a native thread become available to it. If the tasklet needs to be
    started immediately, the additional parameter $now can be passed to mt.start(), so that
    a new native thread may be created if there is no other native thread available for the
    task.

    mt.start() returns a future value which will be used to store the value returned by the
    tasklet. Accessing its value by future.value() will cause the current tasklet to block
    until the value becomes available after the tasklet finishs. If one wants to wait for the
    task for only a limited amount of time, the method future.value() can be used with a
    timeout parameter (a float value for seconds or fraction seconds, negative for infinite
    waiting).

     0.2   Parallelized Code Section Methods

    However, the simplest way to do threaded programming is to use the following parallelized
    code section methods of mt,
      *  iterate():
         Iterate a predefined number of times, or iterate over a list, map or array, and
         execute the code block on each of the items;
      *  map()
         Map a list, map or array to another list, map or array, using the values returned by
         the code block;
      *  apply()
         Apply the values returned by the code block to a list, map or array;
      *  find()
         Find the first item in a list or map the satisfy the condition as tested by the code
         block.

    The default number of threads used by these methods are 2. Examples,

       1  ls = {1,2,3,4,5,6}
       2
       3  # Use 2 threads to iterate 10 times:
       4  mt.iterate( 10 ) { io.writeln( X ) }
       5
       6  # Use 3 threads to iterate over a list:
       7  mt.iterate( ls, 3 ) { io.writeln( X ) }
       8
       9  mt.map( ls, 2 ) { X*X } # produces new list: {1,4,9,16,25,36}
      10  mt.apply( ls, 2 ) { X*X } # ls becomes: {1,4,9,16,25,36}

     0.3   Asynchronous Function Call

    Asynchronous Function Call (AFC) allows a function call to be executed as a tasklet, and
    return immediately a future value that can be use to block on the tasklet and wait for
    its completion.

    Any standard function call followed by !! will start an AFC.

       1  routine MyFunction( n = 10 )
       2  {
       3      for( i = 1 : n ) io.writeln( i )
       4  }
       5  f = MyFunction( 20 ) !!
       6  io.writeln( f.value() )

    When multiple methods of a class instance are called in asynchronous mode, their
    execution will be mutually exclusive, namely, at any given time only call (tasklet) can
    be active. So in this way, the class instance acts just like a monitor.

     0.4   Asynchronous Object

    An asynchronous object is a class instance that is created with asynchronous call mode,

       1  async_objet = some_class( ... ) !!

    When an asynchronous object invokes a method, it will be automatically called in
    asynchronous mode, and start a tasklet and return a future value. Such tasklets are
    queued and and executed in the order they are queued.

    So such asynchronous object acts like an actor in the actor model considering that
    calling methods of such object is just like sending messages to the object with function
    parameters being the message contents. For each instance, these messages are processed
    one by one in the order of receiving.

    Here is an simple example,

       1  class Account
       2  {
       3      private
       4
       5      var balance = 0
       6
       7      public
       8
       9      routine Account( init = 0 ){
      10          balance = init
      11      }
      12      routine Withdraw( amount : int ) => enum<false,true>
      13      {
      14          if ( balance < amount ) return $false
      15          balance -= amount
      16          return $true
      17      }
      18      routine Deposit( amount : int ) => int
      19      {
      20          balance += amount
      21          return balance
      22      }
      23      routine Balance() => int
      24      {
      25          return balance
      26      }
      27  }
      28
      29  acount1 = Account( 100 ) !!
      30  acount2 = Account( 100 ) !!
      31
      32  future1 = acount1.Withdraw( 10 )
      33  if( future1.value() == $true ) future2 = acount2.Deposit( 10 )
      34
      35  future3 = acount1.Deposit( 20 )
      36
      37  io.writeln( 'Balance in account1:', acount1.Balance().value() )
      38  io.writeln( 'Balance in account2:', acount2.Balance().value() )

    Like calling mt.start(), calling a method on an asynchronous object will return a future
    value, which can be used to check the status of the asynchronous call.

     0.5   Communication Channels

    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 essential methods of channel are:
      *  send(): for sending data to the channel;
      *  receive(): for receiving data from the channel;
      *  select(): for selecting a group of channels;
    See dao.concurrent.channel for details. Here is a simple example,

       1  chan = mt::channel<int>(2)
       2
       3  produce = mt.start {
       4      index = 0;
       5      while( ++index <= 10 ){
       6          io.writeln( 'sending', index )
       7          chan.send( index )
       8      }
       9      chan.cap(0)  # set channel buffer size to zero to close the channel;
      10  }
      11
      12  consume = mt.start {
      13      while(1){
      14          data = chan.receive()
      15          io.writeln( "received", data );
      16          if( data.status == $finished ) break
      17      }
      18  }