For simplicity’s sake, we will consider two active threads in this analysis: the main thread, running the event loop, and the Dezyne private thread, consuming events from dzn::pump.
The behaviour we described as ‘blocking’ is the cancellation process of the Timer. This process is started when in the Alarming state, a valid password is entered. Password entry is done through the passwordEntered event on the IController port of the AlarmSystem. This is where the call stack begins: invoking passwordEntered from the main thread.
Because AlarmSystem is generated with a thread-safe-shell, invoking the passwordEntered event is done with the dzn::shell functionality from the Dezyne runtime libraries. This means the main thread will be blocked until the Dezyne private thread has completed processing the event. Important: this is not because of ‘blocking’! This behaviour is fully because of the thread-safe-shell.
Once the event is scheduled in dzn::pump, at some point in time it will be picked up by the Dezyne private thread. Part of the processing of the passwordEntered event is the ‘blocking’ iTimer.cancel call:
The processing of the passwordEntered event is done on the Dezyne private thread, but remember that the main thread is blocked until the related return statement is sent (signaling that the event has been fully processed). Now, when the Dezyne private thread invokes the iTimer.cancel event, it will encounter ‘blocking’ as the implementation of iTimer.cancel in RobustTimer is ‘blocking’:
The Dezyne runtime libraries provide support for ‘blocking’ in the sense that an execution on the Dezyne private thread can be suspended and released again, which ‘blocking’ makes use of. Invoking a ‘blocking’ event suspends the execution of the current event from the dzn::pump and starts execution of the next available event. This subtle implementation in the Dezyne runtime is how the blocked execution can be released again; the release will occur from another event scheduled in dzn::pump. In the figure above, this other event is ext_iTimer.cancelled. When the execution is released, the Dezyne private thread can continue processing the iTimer.cancel event which eventually returns and both threads are released again.