Statically allocated storage within a module is accessible to all the functions of that module, and there is no explicit mechanism in Limbo for synchronizing concurrent updates to this storage from several tasks. However, it is straightforward to build a variety of concurrence-control mechanisms by using channel communications.
An example is a module that implements a Monitor
abstract data type. Each instance of Monitor
has a lock
and an unlock
operation; calling lock
delays if another task holds the lock; calling unlock
releases the lock and enables any other task attempting to execute lock
.
implement Mon; Mon: module{ Monitor: adt { create: fn(): Monitor; lock: fn(m: self Monitor); unlock: fn(m: self Monitor); ch: chan of int; }; }; Monitor.create(): Monitor { m := Monitor(chan of int); spawn lockproc(m.ch); return m; } Monitor.lock(m: self Monitor){ m.ch <- = 0; } Monitor.unlock(m: self Monitor){ <-m.ch; } lockproc(ch: chan of int){ for (;;) { <-ch; # wait for someone to lock ch <-= 0; # wait for someone to unlock } }It would be used like this:
mp : Mon; Monitor : import mp; mp = load Mon "..."; lck := Monitor.create(); . . . lck.lock(); # region of code to be protected; # only one thread can execute here at once. lck.unlock();The
create
method of Monitor
allocates an instance of a Monitor
containing an initialized channel. It also creates a thread executed in the lockproc
routine, which repeatedly reads from the channel, then writes on it. The values transmitted over the channel are of no interest; it is the pure fact of communication that is put to use. The lock
routine sends a message; in the idle state, the lockproc
thread reads it and the sender proceeds. Meanwhile, lockproc
tries to send a message over the same channel. If another thread attempts to lock
there is no reader for the channel, and so its transmission will block. At some point, the thread that gained the lock calls unlock
which receives from the channel. Depending on timing, this reception enables execution of either lockproc
or one of the threads attempting to send via lock
.