[NAME]
ALL.module.standard.sync

[TITLE]
Synchronization

[DESCRIPTION]

Mutex, conditional variable and semaphore are the convetional way for thread 
synchronization. These constructs synchronize tasklet by block the native threads, so
they are not the recommended way for synchronization and communication channels are the
preferrable way.

 0.1  Mutex 

Mutex can be used to synchronize the accessing of shared data structures. It has two
state: locked and unlocked. A mutex can be locked by only one thread. A thread is
suspended when it attempt to lock a mutex which has been locked by another thread.
     
   1  mutex = mutex();
     
Then it can be locked or unlocked by,
     
   1  mutex.lock();
   2  mutex.unlock();
   3  mutex.trylock();
     
By calling lock(), the calling thread will be block if the mutex is already locked by 
another thread. If the mutex is locked by the same thread, a second calling of lock() 
may cause a deadlock. trylock() is the same as lock() except that it will return 
immediately instead of blocking the calling thread if the mutex is already locked.

 0.2  Condition Variable 

Condition variable is a synchronization device which allow a thread to be suspended if a
condition is not satisified and resume execution when it is signaled. The basic
operations on a condition is: wait on the condition, or signal the condition.
     
   1  condvar = condition();
     

Condition variable should always be used together with a mutex. To wait on a condition,
     
   1  mtx.lock()
   2  condvar.wait( mtx );
   3  mtx.unlock();
     

To wait on a condition for a maximum time,
     
   1  mtx.lock()
   2  condvar.timedwait( mtx, seconds );
   3  mtx.unlock();
     

seconds can be a decimal, for example, condvar.timedwait( mtx, 0.005 ) will wait for 
five miliseconds.

 0.3  Semaphore 

Semaphore can be used to set a limit on resources. It maintains a count for the resource,
and allows a thread to proceed, when it attempts to decrease a non-zero count. If the
count already reaches 0 before the decrement, the thread will be suspended until the
count becomes non-zero. When the thread finished using the resource, it should increase
the count of semaphore. A semaphore must be created with an initial count,
     
   1  sema = semaphore( count );
     

To access a resource guarded by a semaphore, use,
     
   1  sema.wait()
     
If the resource is acquired, the count of sema will be decreased.
To release the resource, use
     
   1  sema.post()
     
which will increase the count.

 0.4  State 
State is an abstraction layer for multiple condition variables coupled with the
principles of atomic operations. Semantically, it represent a state of certain process or
object which can be set, altered or waited upon by arbitrary number of concurrent tasks. 
A state contains single value which can be assigned or modified using test-and-set and
fetch-and-add principles. One or more threads can wait until a state reaches certain
value, in this case the synchronization is similar to using conditional variables with
broadcasting.
A state can represent an int, float, double, complex or enum value: 
     
   1  st = state<int>(0);
   2  
   3  type status = enum<on; off; running; idle; finished; canceled>
   4  st2 = state<status>($on + $idle);
     

To perform basic read and write, value() and set() are provided, the latter returns the 
old value of a state:
     
   1  if (st.value() == 0)
   2      old = st2.set($off);
     

alter(old, new) can be used to assign new value to a state if it currently contains old 
value. The routine returns non-zero if the operation has succeeded:
     
   1  success = st.alter(0, 1);
   2  
   3  if (success){
   4      ... #will be executed by the only succeeded thread
   5  }
     

add() and sub() are meant to add/substract for numeric values and append/remove symbols 
for a combined enum. The old value of state is returned:
     
   1  old = st.sub(1);
   2  st2.add($finished);
     

To block the current thread until a state is assigned the desired value, wait() is to be
used. A timeout may specified, in this case the routine will return zero if time-outed. 
To determine what values are currently awaited by other threads, waitlist() is provided:
     
   1  if (2 not in st.waitlist())
   2      success = st.wait(1, 5.0);