Executing an EMont model
Executing a PQR Cluster
Only the leaf activities of a PQR cluster are eligible for execution with the restriction that leaf nodes must have a direct upwards path to the activity in the PQR cluster that has been activated.
Executing a Compound Cluster
A compound activity is comprised of a number of child activities that are performed in particular sequences. Executing a compound activity means that its child activities are executed until they are all done. A compound activity can be nested to arbitrary depths, that is, a compound activity can contain a compound activity, and so on. The nested activities form a compound cluster indicated with the OR annotation.
Just like leaf (Q - how) activities in a PQR cluster, an activity in a compound cluster takes conditions as input and produces updated conditions. But unlike a Q activity, a compound cluster activity is not triggered by conditions, instead the executing is determined by sequence relations, such as activity B follows (seq relation) activity A, or either A or (alt relation) B is chosen. A PQR cluster, indicated with EXOR, can be part of an activity sequence. Likewise, a leaf (Q - how) activity can be a compound cluster. In this way, a compound and a PQR cluster are nested in an alternating fashion.
The leaf (Q - how) activity value of the overarching PQR cluster is calculated after its compound activity, if any, terminates. This is solely done on the basis of the contributes and depends relations associated with the leaf activity. That is, no values from compound activities are propagated to an overarching PQR cluster.
Algorithm
Thread info
- mode: enum of Running, Active, Joining (if needed), Suspended.
- state: refers to the state leading via (conditional) edges to possibly multiple primitives in (zero or more) PQR and (zero or one) compound cluster of which one will be executed in the end.
- parent: refers to the parent (suspended) thread.
- children: list of forked child threads.
Lists
- Active list: list of active threads to be executed provided a primitive is eligible for execution. The Active list is searched for this primitive on a FCFS basis.
Pseudo code
create start thread and put it on the Active list
while (Active list ≠ empty) do
- currentThread := get first eligible thread from Active list (exactly one primitive to be executed)
- // a primitive is eligible for execution if:
- // 1 – in case of a join, all sibling threads in joining (ready to join) state
- // 2 - guard evaluates to true
- // 3 – depends evaluates to true
- // 4 – sync semaphore does not block
- currentThread.mode := Running
- while (currentThread.mode = Running) do
- fork or join // fork en join are side effects of the transition to the primitive
- execute the primitive, i.e., updating conditions
- determine the next primitive(s) to be executed // should be zero or one primitive based on the four criteria
- if (number of primitives = 0) then // a thread switch is needed because this thread cannot continue right now
- currentThread.mode := Active
- put currentThread of the Active list
- elseif (primitive is part of PQR cluster) then // voluntary yield to let another thread seize control
- currentThread.mode := Active
- put currentThread on the Active list
- elseif (primitive is part of the compound cluster) then
- currentThread.state := end state of current primitive
- else
- // there is or should be no other case
- fi
- if (number of primitives = 0) then // a thread switch is needed because this thread cannot continue right now
- od
od <accesscontrol>Access:We got to move</accesscontrol>