INTERACTOR is a special descriptor, which starts a piece of Python code to be executed in a thread separated from the thread of the SVM simulator. (If there are multiple INTERACTOR descriptors, the code under them is literally concatenated.
The code under the INTERACTOR descriptor is started after the initializer of the model is executed, but before the simulation of the model actually starts. This code should first initialize the user interface and then call the start method of the eventhandler object. This starts the simulation, and the model begins to accept events and produce outputs. The interactor does not exit after this, but it usually enters a loop. The code in this loop repeatedly accepts events from the user via the interface, and feeds those events to the model by calling the EVENT predefined macro or the event method of the eventhandler object.
The following example (inter1.des) demonstrates a textual model-specific interface:
STATECHART: A [DS] INTERACTOR: import thread import string lock=thread.allocate_lock() # make sure the model is started before the events are sent to it lock.acquire() eventhandler.start(lock) lock.acquire() lock.release() # repeatedly handle events cmd="" while cmd!="quit": sys.__stdout__.write("CMD > ") cmd=string.strip(sys.__stdin__.readline()) if cmd!="quit": # split the cmd into [event, param] tuple [event, param]=string.split(cmd, ",") lock.acquire() [EVENT(string.strip(event), [eval(string.strip(param))], lock)] lock.acquire() lock.release() # shutdown the simulator eventhandler.shutdown() TRANSITION: S: A N: A E: eval O: [DUMP("result: "+str([PARAMS]))]
The simulation result is as following:
CMD > eval, 1+1 result: 2 CMD > eval, "message"+": %s"%"Hello World" result: message: Hello World CMD > eval, 2*3.1415927*0.5 result: 3.1415927 CMD > quit
Here are the two points to be emphasized:
To avoid the error caused by sending events to the model before it is fully initialized and the simulation is started correctly, the interactor must wait until the start event is handled. To ensure this, it calls the start method of an already acquired lock. The simulator releases the lock when it is started, but before that, the next acquisition of the same lock is blocked. This blocking causes the interactor thread to wait until the simulator is started.