load help;

@[name]
dao.concurrent
@[name]

@[title]
Concurrent Programming
@[title]

@[text]

Dao has native support for concurrent programming on multicore computers.
The basic concurrent computational unit in Dao is a tasklet which consists
of a virtual machine process (context) and a future value (handle).
A tasklet is much cheaper than a native thread, because only active tasklets
are attached to native threads for execution.


Dao provides two main features for concurrent programming:
one is the multithreading module @[green]mt@[green];
the other is the asynchronous class.
Dao also provides communication channels for tasklets 
to communicate and synchronize with each other by channels.
@[text]


################################################################################
################################################################################
#### Multithreading
################################################################################
################################################################################
@[name]
dao.concurrent.threading
@[name]
@[title]
Multithreading Module
@[title]

@[text]

The multithreading module @[green]mt@[green] offers methods 
for creating tasklets and synchronization constructs such as
mutex, condition variable, semaphore and as well as channels.
This module also provides a list of parallelized methods that
can make some typical parallelization tasks straightforward.


@[subsection]
Starting Tasklet
@[subsection]

The simplest way to start a tasklet is to use the functional method
@[green]mt.start@[green] to run an expression or a block of codes:
@[code]
a = 123
fut = mt.start { a*a }
fut2 = mt.start {
	for( i = 1 : 1000 ) b = a*a
}
@[code]
This functional method is implemented as a code section (code block as in Ruby)
method, and can take a block of code as an additional implicit parameter.
@[green]mt.start@[green] returns the created tasklet in the form of a future value.
The created tasklet may be executed by a reused thread from the internal
thread pool or by a newly created thread.


@[subsection]
Future Value
@[subsection]

Future value is a type that represents a value that is available only
after a tasklet has been completed.
The future value for the tasklet can be used to perform simple scheduling
such as blocking the current thread indefinitely or a finite amount of time
to wait for the thread to finish. For example,
@[code]
fut.wait()
fut2.wait( 0.1 )
@[code]
Its value can be obtained by,
@[code]
value = fut.value()
@[code]
which will block the current tasklet and wait for the completion of the tasklet
represented by @[cyan]fut@[cyan].



@[subsection]
Using Parallelized Code Block Methods
@[subsection]

However, the simplest way to do parallel programming is to use the
parallelized functional methods of @[green]mt@[green], which provides
the following parallelized functional methods,
@[list]
-- @[green]iterate()@[green]:

   Iterate a predefined number of times, or iterate over a list, map or array,
   and execute the code block on each of the items;

-- @[green]map()@[green]

   Map a list, map or array to another list, map or array, using the values
   returned by the code block;

-- @[green]apply()@[green]

   Apply the values returned by the code block to a list, map or array;

-- @[green]find()@[green]

   Find the first item in a list or map the satisfy the condition as
   tested by the code block.
@[list]

Examples,
@[code]
mt.iterate( 10 ) { io.writeln( X ) }
mt.iterate( {1,2,3,4,5,6}, 3 ) { io.writeln( X ) }
@[code]


@[text]





################################################################################
################################################################################
#### Asynchronous Object
################################################################################
################################################################################
@[name]
dao.concurrent.asyncall
@[name]

@[title]
Asynchronous Function Call
@[title]

@[text]

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 @[green]!!@[green] will start an AFC.
@[code]
routine MyFunction( n = 10 )
{
	for( i = 1 : n ) io.writeln( i )
}
f = MyFunction( 20 ) !!
io.writeln( f.value() )
@[code]


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 @[link]monitor@@http://en.wikipedia.org/wiki/Monitor_(synchronization)@[link].

@[text]




################################################################################
################################################################################
#### Asynchronous Object
################################################################################
################################################################################
@[name]
dao.concurrent.asyncobject
@[name]

@[title]
Asynchronous Object
@[title]

@[text]


An asynchronous object is a class instance that is created with asynchronous call mode,
@[code]
async_objet = some_class( ... ) !!
@[code]

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 
@[link]actor model@@http://en.wikipedia.org/wiki/Actor_model@[link]
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,
@[code]
class Account
{
	private

	var balance = 0

	public

	routine Account( init = 0 ){
		balance = init
	}
	routine Withdraw( amount : int ) => enum<false,true>
	{
		if ( balance < amount ) return $false
		balance -= amount
		return $true
	}
	routine Deposit( amount : int ) => int
	{
		balance += amount
		return balance
	}
	routine Balance() => int
	{
		return balance
	}
}

acount1 = Account( 100 ) !!
acount2 = Account( 100 ) !!

future1 = acount1.Withdraw( 10 )
if( future1.value() == $true ) future2 = acount2.Deposit( 10 )

future3 = acount1.Deposit( 20 )

io.writeln( 'Balance in account1:', acount1.Balance().value() )
io.writeln( 'Balance in account2:', acount2.Balance().value() )
@[code]

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


@[text]



################################################################################
################################################################################
#### Channels
################################################################################
################################################################################

@[name]
dao.concurrent.channel
@[name]

@[title]
Communication Channel
@[title]

@[text]

Tasklets (represented by future values) created from @[green]mt::start@[green],
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 
@[green]communication channels@[green].


The @[green]channel@[green] 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,
@[code]
chan = mt::channel<int>()
@[code]
Here @[magenta]channel@[magenta] is prefixed with @[magenta]mt::@[magenta],
because @[green]channel@[green] is defined in the built-in @[green]mt@[green]
multi-threading module.


The type argument @[magenta]int@[magenta] indicates this channel can only
be used to transmit integers. Currently, only primitive types 
(@[green]int@[green], @[green]float@[green], @[green]double@[green], 
@[green]complex@[green], @[green]string@[green], @[green]enum@[green]) 
plus @[green]array@[green] types, and their composition through 
@[green]list@[green], @[green]map@[green] and @[green]tuple@[green] 
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:
@[list]
--@[code(dao)]buffer( self :channel<@V> ) => int@[code(dao)]

It returns the number of unprocessed data items in the channel buffer.

--@[code(dao)] cap( self :channel<@V> ) => int @[code(dao)]

Return the channel capacity.

--@[code(dao)] cap( self :channel<@V>, cap :int ) => int @[code(dao)]

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.

--@[code(dao)] send( self :channel<@V>, data :@V, timeout :float = -1 ) => int @[code(dao)]

Send a data item with a timeout. A negative timeout parameter means infinite waiting. It return 1 upon timeout, 0 otherwise.

--@[code(dao)] receive( self :channel<@V>, timeout :float = -1 ) => tuple<data :@V|none, status :enum<received,timeout,finished>> @[code(dao)]

Receive a data item with a timeout. A negative timeout parameter means infinite waiting. It returns a tuple with the following possible values:
 @[list(sub)]
 -- (data, $received);
 -- (none, $timeout);
 -- (none, $finished);
 @[list(sub)] 

--@[code(dao)] select( group :list<@T>, timeout = -1.0 ) => tuple<selected: none|@T, value :any, status :enum<selected,timeout,finished>> @[code(dao)]

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:
 @[list(sub)]
 -- (channel, data, $selected);
 -- (none, none, $timeout);
 -- (none, none, $finished);
 @[list(sub)] 
As the signature indicates, this is a static method.

@[list]

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:
@[code(dao)]
load sys

chans = { mt::channel<int>(1), mt::channel<string>(1) }

mt.start {
    index = 0;
    while( ++index <= 10 ){
        if( rand(2) ){
            io.writeln( "sending integer:", index );
            chans[0].send( index )
        }else{
            io.writeln( "sending string: S" + (string) index );
            chans[1].send( 'S' + (string) index )
        }   
        sys.sleep(0.5)
    }   
    # set channel buffer sizes to zero to close them:
    chans[0].cap(0) 
    chans[1].cap(0)
}

while( 1 ){
    data = mt::channel::select( chans, 0.2 )
    io.writeln( "received:", data );
    if( data.status == $finished ) break
}
@[code(dao)]

@[text]
