With YAKINDU Statechart Tools 4.0, the way the client API is generated slightly changed. These incompatible changes were introduced to have a more concise Application Programming Interface. This chapter explains in detail how to migrate client code to the new generated API.
The default API to access out events changed. In 3.x releases out events must be checked using event isRaised()
methods. With release 4 an observable based notification API is the default. The 3.x compatible API can be generated using the new generator feature in your sgen files.
feature OutEventAPI {
getters = true
observables = false
}
This feature is available in all code generators and observables can be used together with the old style API.
The generated source and header files use the name of the statechart as it is defined without upper casing the first letter. In case your statechart uses time events or defines operations, an additional header is generated. We changed the suffix of this header from Required to _required:
Before: StatechartRequired.h
After: statechart_required.h
We removed the Iface suffix from all operations that access variables, events and operations that are declared within an interface. This can be migrated by simply removing the Iface suffix:
Before: coffeeMachineIface_raise_userEvent(handle);
After: coffeeMachine_raise_userEvent(handle);
We removed the Iface prefix of the named interfaces. Assume an interface User with an event on_button:
Before: coffeeMachineIfaceHeater_raise_overheated(handle);
After: coffeeMachine_heater_raise_overheated(handle);
We changed the lifecycle functions runCycle, isStateActive, isActive and isFinal to have a consistent naming convention for the generated C API. Same holds for setTimer, unsetTimer and raiseTimeEvent functions in case time triggers are used.
Before: coffeeMachine_runCycle(handle);
After: coffeeMachine_run_cycle(handle);
Before: coffeeMachine_isStateActive(handle, ...);
After: coffeeMachine_is_state_active(handle, ...);
Before: coffeeMachine_isActive(handle);
After: coffeeMachine_is_active(handle);
Before: coffeeMachine_iFinal(handle);
After: coffeeMachine_is_final(handle);
Before: coffeeMachine_setTimer(handle, ...);
After: coffeeMachine_set_timer(handle, ...);
Before: coffeeMachine_unsetTimer(handle, ...);
After: coffeeMachine_unset_timer(handle, ...);
Before: coffeeMachine_raiseTimeEvent(handle, ...);
After: coffeeMachine_raise_time_event(handle, ...);
CoffeeMachine* coffeeMachine = new CoffeeMachine()
coffeeMachine->init()
if(! coffeeMachine->check()) {
cout << "something has not been set" << endl;
return -1;
}
State machine classes inherit from a StatemachineInterface. This is now declared in the header sc_statemachine.h under the namespace sc. A state machine does not declare an init() function anymore. The initialization is done in the class constructor instead. The runCycle method is also not part of the generic interface anymore.
State machines that run with the @CycleBased execution scheme now inherit from the CycleBasedInterface which declares a public runCycle() function.
State machines that use time triggers inherit from TimedInterface instead of TimedStatemachineInterface. This interface declares functions to set a timer service which are called setTimerService(TimerServiceInterface) / getTimerService() instead of setTimer(TimerInterface) / getTimer(). The former TimerInterface was renamed accordingly to TimerServiceInterface. Both, the TimedInterface and the TimerServiceInterface are declared in the header file sc_timer.h under the namespace sc::timer:
namespace sc {
namespace timer {
class TimedInterface {
public:
virtual void setTimerService(sc::timer::TimerServiceInterface* timerService) = 0;
virtual sc::timer::TimerServiceInterface* getTimerService() = 0;
...
};
class TimerServiceInterface { ... };
We removed the underscore in favor of camelCase notation for all getter/setter and raise methods. Assume a default interface with an event userEvent.
Before: coffeeMachine->raise_userEvent(lastEvent);
After: coffeeMachine->raiseUserEvent(lastEvent);
We removed the getSCI prefix_ from the state machine. Assuming an interface called Light with a variable called on:
Before: coffeeMachine.getSCI_Heater()->raise_overheated()
After: coffeeMachine.heater()->raiseOverheated()
We have removed some parameters from the GeneralFeatures feature:
Moreover, the InterfaceObserverSupport parameter has been replaced by the new OutEventAPI feature. In order to react on out events you just need to subscribe an observer on the out event observables which are generated for you by default. As the expected observer interface only declares one function, you can simply use lambda expressions like this to react on out events:
coffeeMachine.heater().getTemperatureReached().subscribe((value) -> System.out.println("Set temperature is " + value + "."));
If you are using the event getter functions isRaisedEvent() and getEventValue(), you need to enable their generation with the parameter getters in the OutEventAPI feature.
The Naming feature now contains two more options:
The state machine is generated into the package as defined by the basePackage parameter and/or the statechart’s namespace. If none of the two is defined, the state machine is generated into the default package. In that case, the generator model will contain a warning.
We do not add a Statemachine suffix for state machine classes anymore.
State machine classes inherit from an IStatemachine interface as before. This interface does not declare an init() function anymore. The initialization is done in the class constructor instead. The runCycle method is also not part of the generic interface anymore.
State machines that run with the @CycleBased execution scheme now inherit from the ICycleBased interface which declares a public runCycle() function.
State machine classes do not inherit from a statechart specific interface anymore which reflected the statechart’s definition section.
State machines that use time triggers inherit from ITimed interface instead of ITimerCallback. The ITimed interface declares a function to set a timer service, and the callback function to raise a time event. The timer service interface is also renamed from ITimer to ITimerService.
public interface ITimed {
public void raiseTimeEvent(int eventID);
public void setTimerService(ITimerService timerService);
}
We removed the getInterface prefix from the state machine. Assuming an interface called User with an event called operate:
Before: coffeeMachine.getInterfaceHeater().raiseOverheated();
After: coffeeMachine.heater().raiseOverheated();
We removed the getInterface() getter for the default interface. You can access all events and variables that are defined within the default interface directly from the state machine instance now:
Before: coffeeMachine.getInterface().raiseUserEvent())
After: coffeeMachine.raiseUserEvent()