Here we will show how to implement a Monitor
system using preemptive coroutines and Semaphore.
Below we show our first version of class Monitor
:
class Monitor:
entry:
mutex.wait
inner(entry)
mutex.signal
%private
mutex: obj Semaphore(1)
A Monitor
-object has a Semaphore
attribute and a local method pattern, entry
, which is to be used as a supermethod for methods in subclasses of Monitor
. As can be seen, entry
has an inner(entry)
; mutex.wait
is executed before inner(entry)
and mutex.signal
is executed after inner(entry)
.
The Account
class may be described as a subclass of Monitor
in the following way:
class Account: Monitor
deposit(amount: var float): entry
balance := balance + amount
withdraw(amount: var float): entry
balance := balance - amount
%private
balance: var float
If anAccount
refers to an Account
-object, then execution of anAccount.deposit(200)
has the effect that the supermethod entry
of deposit
works like a wrapper around the statement balance := balance + amount
. This ensures that mutex.signal
is executed before the statement and mutex.signal
is executed afterwards. The same is the case for execution of a anAccount.withDraw(300)
. All in all, using entry
as a supermethod ensures that at most one deposit
or withdraw
may be executed at the same time, which guarantees exclusive acces to data-items within the Monitor
object.
In section , Monitor
is used as part of class that also defines a MonitorProcess
class. We will show how to define such a system. It will contain the elements shown below:
class MonitorSystem
class Monitor: ...
class MonitorProcess: ...
%private
scheduler: obj ...
SQS: obj ProcessQueue
Class Monitor
is defined as shown above. Class MonitorProcess
is supposed to be a superclass of all parallel objects in the MonitorSystem
. The scheduler object handles scheduling of MonitorProcess
-objects and SQS
is a queue of MonitorProcess
-objects that are ready for being executed.
Class MonitorProcess
may be defined as follows:
class MonitorProcess:
start:
status := ACTIVE
SQS.insert(this(MonitorProcess))
status: var integer
inner(MonitorProcess)
status := TERMINATED
A MonitorProcess
has four attributes:
- A
start
method that sets the status of theMonitorProcess
object toACTIVE
. - An integer variable
status
holding the status of theMonitorProcess
. - An
inner
-statement that implies execution of items in a subclass ofMonitorProcess
. - Finally a statement setting
status
toTERMINATED
whereafter execution of theMonitorProcess
object ends.
Next we describe the Scheduler
object:
scheduler: obj
active: ref MonitorProcess
cycle
active := SQS.next
if (active <> none) :then
active.attach(100)
if (active.status = ACTIVE) then
SQS.insert(active)
The scheduler
has a data-item active that is a reference to the MonitorProcess
object currently being executed.
Then it has a cycle
-statement that forever executes:
- A reference to the next
MonitorProcess
in the queueSQS
of activeMonitorProcess
-objects is assigned toactive
. - If there are no references in
SQS
,active
will get the datumnone
. - If
active
is notnone
, the methodactive.attach(100)
is invoked implying that execution ofactive
is resumed. Ifactive
has not bee executed before, execution starts from the beginning ofactive
; ifactive
has been executed before ans execution has been suspended, execution is resumed after the point of suspension. Active
will be preemptively suspended after 100 time units, but it may also terminate before the 100 time units have appeared.- If active
active.status = ACTIVE
andactive
is re-inserted into SQS. - Otherwise
active
has terminated (status = TERMINATED
) execution and thus not re-inserted intoSQS
.