Advanced

Understanding event handling

The event described in Event types above are defined by Channel Access but it can be important to understand exactly their behaviour, to avoid getting strange results in edge conditions.

When the user call the method connect(), the library will look on the local network and search (via UDP broadcasts) for any IOC declaring a PV with the desired name. This may take a small amount of time. After that a TCP connection is created with the IOC, if not already available. In fact, the same TCP connection to an IOC is shared for all the PVs declared on that IOC. Now the Channel Access protocol registers a monitor on those PVs, so that each time they change status, an event is generated by the IOC and sent to the FSM. This is similar to an interrupt mechanism, so that pysmlib doesn’t have to constantly poll for changes, which would kill network performances. When the connection finally is set up, two events reaches the FSM, hopefully in this order:

  1. A connection event, with connected set to True and value set to None.

  2. A change event, with value set to the new value.

This means that it is not sufficient to wait for the connection to be able to read an input, but the first change event must have arrived. In cases where multiple inputs are connected at the same time, it can arrive multiple events later. For this reason there is a specific method to check the availability of the first value after a connection: initialized(). This will return True if an input is connected and has received its first value.

Pysmlib has been designed so that the status of an input does not change while executing a state. This means that the code is executed exactly once per event received, and the updates brought by the events are available only after they are evaluated. For example, when a change event arrives, it is added to a FIFO list. When all the preceding events have been evaluated, the event is removed from the list, its new value is written to the corresponding input and the current state is executed. In cases where there are a lot of received events, there may be a certain delay between the time of arrival and the time when it is evaluated. For this reason it is important to keep the states simple and non-blocking.