Event Listening
Listening to Object Events
Objects have the ability to listen to the events of other objects. Examples of these events include a model reset, a state change (e.g. idle to busy), or accepting a flowitem. A complete list of engine events is found in basicmacros.h, included with the FlexsimContent; the macros for events all follow the format SM_EVENTNAME.
Broadcaster Objects
All FlexSimObjects can have an attribute node called listeners. Subnodes of the listeners attribute must be coupling data, and they must point to a subnode of a listener object. An example of a listener node is shown below.
This processor is broadcasting its events to ListenerObj and to Sink3. All of the processor's events send a signal to Sink3. To filter the events that send a signal to a particular listener, simply add a subnode to the listener node with number data. The number data specified is a bitmask for which events signal the listener; 128, the filter shown above, is the value that only sends SM_ACCEPT events. In C++, the bitshift operator can be used to create this bitmask flag. For example, to create a flag that allows signals for both the reset event and the give event (e.g. a flowitem leaving a processor), the filter might be assigned as follows (in C++):
set(filterNode, (1 << SM_RESET) | (1 << SM_GIVE));
Listener Objects
The event handling code lives in a listening object. Any node can become a listener object as long as it meets the following requirements:
- The node has object data.
- The node has an OnListen or OnPreListen (or both) attribute, built as FlexScript.
- The node has a coupling node as an attribute, the link to the broadcaster.
A simple example is shown in the figure below:
Every event that is not filtered will execute the OnPreListen function just before the event actually takes place, and the OnListen function just after. The parameters that are available within the OnPreListen and the OnListen include the following:
- c - the listening object
- i - the broadcasting object
- listenerinfo(1) - the event code (SM_ENTER, etc.)
- listenerinfo(2) - the broadcasting object (same as i)
- listenerinfo(3) - the coupling node in the broadcasting object
Listening to Functions
It is also possible to use a listening object to listen to function nodes called with either function_s() or nodefunction(). To do this, the node must meet the following requirements:
- The node must have a coupling subnode, linking to a listener object.
- The node and the coupling subnode must be switched to active listeners using
switch_activelisteners(theNode, 1)
In this case, the OnPreListen function of the listener object will execute just before the function runs, and the OnListen function will execute just after. However, the variables that are available in the OnPreListen and the OnListen are very different, as shown below:
- c - the listener object
- parval/parnode/parstr(n) - any variables passed to the original function
Overriding the Return Value
Another interesting capability of function listeners (rather than object event listeners) is the ability to override the return value of the broadcasting function. There is an application command that can accomplish this task. It should only be called in the OnListen function of the listening object.
applicationcommand("overridereturnvalue", myVal);
This will force myVal as the return value for the broadcasting function.
Handling Events with FlexSimEvent Objects
It is also possible to attach event handling code using a FlexSimEvent object. This requires a custom class that extends FlexSimEvent, which extends CouplingDataType. A node with this kind of custom data can be used to listen to both object events and to functions.
Listening to Object Events
To listen to an object event, simply place a subnode pointing to custom data (again, that extends FlexSimEvent) in the listeners attribute of any object. This custom data should configure the FlexSimEvent members it inherits as follows:
- code - This value is a bitmask filter for which events trigger the custom object code. It can be determined using the (1 << SM_SOMEEVENT) | (1 << SM_SOMEOTHEREVENT) method (see Broadcaster Objects for more detail).
- time - This value is actually a flag for determining
if the object is triggered pre event, post event, or both. Possible values are shown below:
- 0 - post event
- 1 - pre event
- 2 - post event
- 3 - pre and post event
- execute() - This function must be overriden; it is executed
when the object is triggered. Within this function, the object variables have the following
values:
- code - the current value of the event code (e.g. SM_ACCEPT)
- time - the current event timing (1 for pre event, 2 for post event)
- involved - the listeners attribute of the object
- data - the current callpoint structure
Listening to Functions
Listening to functions with FlexSimEvent objects is identical to listening to object events, with the following exceptions:
- code - this value should be zero, since no event code is present.
- execute() - within this function, the involved variable will be the function node itself.