thread: Concurrent programming with threads

This module provides low-level facilities for using concurrent threads that are executed conceptually simultaneously. The Mutex and Condition classes can be used to synchronize threads and implement communication between threads.

Program execution starts in a special main thread. The execution of a program ends after the main thread ends. If any other threads are executing at program exit, they will be forcibly terminated. It is recommended that programs explicitly end threads by calling join to avoid data loss due to terminated threads.

Class Thread<T>

class Thread(function as def () as T)
Construct a new thread. The thread calls the function with no arguments. The function may be any callable object, and it is the thread function of the new thread.

Thread methods

join() as T
Wait until the execution of the thread stops. Return the value returned by the thread function. If the function raised an exception that was not caught, this method will raise that exception. Join can be called only once for each thread object.

Class Mutex

class Mutex()
Construct a mutex.

Mutex methods

Lock the mutex. A mutex may be locked only once before calling unlock(). If the mutex is already locked by another thread while calling lock(), the calling thread waits until the mutex is unlocked and tries to lock the mutex again until it succeeds.
Unlock the mutex. The mutex must be locked. Only the same thread that has locked the mutex may unlock the mutex.

Class Condition

class Condition()
Construct a condition variable.

Condition methods

wait(mutex as Mutex)
Wait until another thread signals or broadcasts the condition variable. The mutex must have been locked by the current thread before calling this method. This method unlocks the mutex during the wait but locks it again before returning.
Signal one of the threads waiting for the condition variable. If no thread is waiting for the condition variable, this method does nothing.
Signal all of the threads currently waiting for the condition variable. If no thread is waiting for the condition variable, this method does nothing.

Locking policy

Mutex objects are used for mutual exclusion, i.e. to make sure that only a single thread is accessing a resource such as an object, a variable or a file at the same time. Sometimes Mutex objects need to be used even though there is no obvious need for mutual exclusion. Therefore the rules below must be followed very carefully in any code that uses threads.

Each time a thread accesses a variable or an object, if that variable or object may have been modified by another thread since the creation of that thread, that access must be protected my a mutex. Likewise, the operations that actually modify the variable or the object must be protected by the same mutex.

For example, consider two simultaneous threads that call functions F1 and F2:

var Shared = 1

def F1()
  Shared = 2 -- Error!

def F2()
  if Shared == 2 -- Error!

The function F2 accesses a variable that may have been modified by F1 in another thread. This in an error, and to remedy this, all the variable accesses must be protected by a mutex.

Note: As an exception, some classes may perform the required locking automatically. Unless this is explicitly mentioned, however, the caller must take care of locking. Remember that Stream objects and their descendants do not typically perform any locking!