
p. 

==<div style="counter-reset: h1 7 h2 5">==

h2(#codegen_cpp_code_generator). C++ code generator

h3(#codegen_cpp_code_generator_features). C++ code generator features

The C++ generator features are the same a the "C generator features":../user-guide/code_generation_c.html#codegen_c_code_generator_features, plus the following ones.

==<!-- Start sgen_feature_generatoroptions -->==

h4(#codegen_cpp_generatoroptions_feature). GeneratorOptions feature

The *GeneratorOptions* feature allows to change the behavior of the C++ generator:

* _innerFunctionVisibility_ (String, optional): This parameter is used to change the visibility of inner functions and variables. By default @private@ visibility is used. It can be changed to @protected@ to allow function overriding for a class which inherits from the generated state machine base class.
* _staticOperationCallback_ (Boolean, optional): If this parameter is set to _true_, the callback function declaration for statechart operations is static and the functions are called statically by the state machine code.

==<div class="example">==

Example:

bc. feature GeneratorOptions {
    innerFunctionVisibility = "protected"
    staticOperationCallback = true
}

==</div>==

==<!-- End sgen_feature_generatoroptions -->==


==<!-- Start sgen_feature_includes -->==

h4(#codegen_cpp_includes_feature). Includes feature

The *Includes* feature allows to change the way include statements are generated:

* _useRelativePaths_ (Boolean, optional): If this parameter is set to _true_, relative paths are calculated for include statements, otherwise simple includes are used. Default value is _true_.

==<div class="example">==

Example:

bc. feature Includes {
    useRelativePaths = false
}

==</div>==

==<!-- End sgen_feature_includes -->==


==<!-- Start sgen_feature_api -->==

h4(#codegen_cpp_api_feature). API feature

The *API* feature allows to change the way include statements are generated:

* _checkUnimplementedOCBs_ (Boolean, optional): If set to _true_, the _init_ function returns an error code, otherwise the _init_ function's return type is _void_.

==<div class="example">==

Example:

bc. feature API {
    checkUnimplementedOCBs = true
}

==</div>==

==<!-- End sgen_feature_api -->==



h3(#codegen_cpp_specification_of_cpp_code). Specification of C++ code

In order to describe the API specifications of the code generated by the YAKINDU C++ generator, the explanations below are using the _Traffic Light_ sample state machine, see "figure &quot;The _Traffic Light_ sample statechart model&quot;":#codegen_cpp_fig_the_traffic_light_sample_statechart_model. It models a pedestrian crossing with push-button operated traffic lights ("pelican crossing").

p(#codegen_cpp_fig_the_traffic_light_sample_statechart_model). 
!(full)images/docu_TrafficLight.png(The _Traffic Light_ sample statechart model)!

p=. The _Traffic Light_ sample statechart model

###. You can find the C++ sample project _"Traffic Light (C++)":https://github.com/Yakindu/examples/tree/master/traffic_light_cpp_ in the "YAKINDU Statechart Tools examples repository":https://github.com/Yakindu/examples. The C++ example contains statechart, SGen model, graphical widgets, and some glue code to connect the generated code with the widgets. The graphical widgets are based on Qt.

###. FIXME: C: To execute the C example, run the file &#95;org&#95;yakindu&#95;sct&#95;examples&#95;c&#95;trafficlight&#95; as "Local C/C\&#43;\&#43; application" from the Eclipse &#95;Run As&#95; context menu.


h4(#codegen_cpp_generated_code_files). Generated code files

You will find the generated code in the _src-gen_ folder of the traffic light example.

The _StatemachineInterface.h_ header file defines the fundamental state machine interface methods. This file also contains the definition of the abstract class _StatemachineInterface_ which contains pure virtual functions only. It is needed by each particular state machine and is independend from concrete ones.


h4(#codegen_cpp_statemachine_class). Statemachine class

The state machine source code is generated as a C++ class with the same name as the statechart. For example, if the statechart is named _DefaultSM_ the C++ class will also be called _DefaultSM_, and it will be generated in the source code file _DefaultSM.cpp_.


h4(#codegen_cpp_abstract_class_statemachineinterface). Abstract class StatemachineInterface

Each generated state machine implements the interface _StatemachineInterface_:

bc.. 

#ifndef STATEMACHINEINTERFACE_H_
#define STATEMACHINEINTERFACE_H_

/*
 * Basic interface for state machines.
 */
class StatemachineInterface
{
	public:
	
		virtual ~StatemachineInterface() = 0;
		
		/*
		* Initializes the state machine. Used to initialize internal variables etc.
		*/
		virtual void init() = 0;
	
		/*
		* Enters the state machine. Sets the state machine into a defined state.
		*/
		virtual void enter() = 0;
	
		/*
		* Exits the state machine. Leaves the state machine with a defined state.
		*/
		virtual void exit() = 0;
	
		/*
		* Start a run-to-completion cycle.
		*/
		virtual void runCycle() = 0;
		
		/*
		* Checks whether the state machine is active. 
	 	* A state machine is active if it has been entered. It is inactive if it has not been entered at all or if it has been exited.
	 	*/	
		virtual	sc_boolean isActive() = 0;
		
		/*
		* Checks if all active states are final. 
	 	* If there are no active states then the state machine is considered being inactive. In this case this method returns false.
	 	*/
		virtual sc_boolean isFinal() = 0;
};

inline StatemachineInterface::~StatemachineInterface() {}

#endif /* STATEMACHINEINTERFACE_H_ */


h5(#codegen_cpp_fundamental_statechart_methods). Fundamental statechart methods

The generated code contains fundamental methods to initialize, enter, and exit a state machine, as well as a function to execute a run-to-completion step.

The _StatemachineInterface_ interface specifies the four functions _init()_, _enter()_, _exit()_ and _runCycle()_.

<ul><li><p>The _init()_ function is used to initialize the internal objects of the state machine right after its instantiation. Variables are initialized to their respective default values. If the statechart defines any initialized variables, these initializations are also done in the _init()_ function.</p></li><li><p>The _enter()_ function must be called to enter the state machine. It brings the state machine to a well-defined state.</p></li><li><p>The _exit()_ function is used to leave a state machine statefully. If for example a history state is used in one of the top regions, the last active state is stored and the state machine is left via _exit()_. Re-entering it via _enter()_ continues to work with the saved state.</p></li><li><p>The _runCycle()_ function is used to trigger a run-to-completion step in which the state machine evaluates arising events and computes possible state changes. Somewhat simplified, a run-to-completion cycle consists of the following steps:</p><ol style="list-style-type:  decimal;"><li><p>Clear the list of outgoing events.</p></li><li><p>Check whether any events have occurred which are leading to a state change.</p></li><li><p>If a state change has to be done:</p><ol style="list-style-type:  decimal;"><li><p>Make the present state inactive.</p></li><li><p>Execute exit actions of the present state.</p></li><li><p>Save history state, if necessary.</p></li><li><p>Execute transition actions, if any.</p></li><li><p>Execute entry actions of the new state.</p></li><li><p>Make the new state active.</p></li></ol></li><li><p>Clear the list of incoming events.</p></li></ol></li></ul>



h4(#codegen_cpp_time-controlled_state_machines). Time-controlled state machines

If a statechart uses timing functionality, additional classes are generated.

The traffic light example uses timing funtionality, namely _after_ clauses. To support time-controlled behavior, the abstract classes _TimedStatemachineInterface_ and _TimerInterface_ are generated. Also, the main statechart class has two constants: @timeEventsCount@ and @parallelTimeEventsCount@, which are the overall number of time events in the statechart and the maximum number of time events that can be active simultaneously. For example, time events in states within the same region can never be active in parallel, while time events in a parent state can be active together with the time events of child states. You can use these constants in a timer service to allocate sufficient memory for the timers.

The _TimedStatemachineInterface_ interface extends the generated state machine by a _TimerInterface_ data member. The client code must provide an implementation of that interface.

_TimedStatemachineInterface_ also specifies the callback function _raiseTimeEvent(sc_eventid event)_, enabling the timer service to raise time events.

bc.. 

#ifndef TIMEDSTATEMACHINEINTERFACE_H_
#define TIMEDSTATEMACHINEINTERFACE_H_

#include "sc_types.h"
#include "TimerInterface.h"

/*
* Interface for state machines which use timed event triggers.
*/
class TimedStatemachineInterface {
	public:
	
		virtual ~TimedStatemachineInterface() = 0;
		
		/*
		* Set the ITimerService for the state machine. It must be set
		* externally on a timed state machine before a run cycle can be correct
		* executed.
		*/
		virtual void setTimer(TimerInterface* timer) = 0;
		
		/*
		* Returns the currently used timer service.
		*/
		virtual TimerInterface* getTimer() = 0;
		
		/*
		* Callback method if a time event occurred.
		*/
		virtual void raiseTimeEvent(sc_eventid event) = 0;
};

inline TimedStatemachineInterface::~TimedStatemachineInterface() {}

#endif /* TIMEDSTATEMACHINEINTERFACE_H_ */

p. Basically the proper time handling has to be implemented by the developer, because timer functions generally depend on the hardware target used. So for each hardware target a timer service class implementing the _TimerInterface_ interface has to be developed.

Let's have a look at the _TimerInterface_ interface:

bc.. 

#ifndef TIMERINTERFACE_H_
#define TIMERINTERFACE_H_

#include "sc_types.h"

//forward declaration of TimedStatemachineInterface to avoid cyclic dependency
class TimedStatemachineInterface;

/*
 * Basic interface for state machines.
 */
class TimerInterface
{
	public:
		
		virtual ~TimerInterface() = 0;
	
		/*
		 * Starts the timing for a time event.
		 */ 
		virtual void setTimer(TimedStatemachineInterface* statemachine, sc_eventid event, sc_integer time, sc_boolean isPeriodic) = 0;
		
		/*
		 * Unsets the given time event.
		 */
		virtual void unsetTimer(TimedStatemachineInterface* statemachine, sc_eventid event) = 0;
	
		/*
		 * Cancel timer service. Use this to end possible timing threads and free
		 * memory resources.
		 */
		virtual void cancel() = 0;
};

inline TimerInterface::~TimerInterface() {}

#endif /* TIMERINTERFACE_H_ */

p. The _TimerInterface_ interface defines the following functions dealing with timing functionality:

h5(#codegen_cpp_function_settimer). Function setTimer

A state machine calls the _setTimer(TimedStatemachineInterface* statemachine, sc_eventid event, sc_integer time, sc_boolean isPeriodic)_ function to tell the timer service that it has to start a timer for the given time event and raise it after the period of time specified by the _time_ parameter has expired. It is important to only start a timer thread or a hardware timer interrupt within the _setTimer()_ function and to avoid any time-consuming operations like extensive computations, _Thread.sleep(…)_, or waiting. Otherwise the state machine execution might hang within the timer service or might not show the expected runtime behavior.

In order to have the timer service raise the time event periodically, the parameter _isPeriodic_ must be _true_.

h5(#codegen_cpp_function_unsettimer). Function unsetTimer

The state machine calls the function _unsetTimer(TimedStatemachineInterface* statemachine, sc_eventid event)_ to notify the timer service to unset the timer for the given event ID.

h5(#codegen_cpp_function_raisetimeevent). Function raiseTimeEvent

In order to notify the state machine about the occurence of a time event after a period of time has expired, the function _raiseTimeEvent(sc_eventid event)_ must be called on the state machine. For this purpose, the state machine must implement the _TimedStatemachineInterface_ interface.

The time event is recognized by the state machine and will be processed during the next run cycle.

You can conclude that in order to process the time events raised by the timing service without too much latency, the runtime environment has to call the state machine's _runCycle()_ function as frequently as needed. Consider for example a time event which is raised by the timer service after 500 ms. However, if the runtime environment calls the state machine's _runCycle()_ function with a frequency of once per 1000 ms only, the event will quite likely not be processed at the correct points in time.


h4(#codegen_cpp_accessing_interfaces_variables_and_events). Accessing interfaces, variables and events

The client code can read and write state machine variables and raise state machine events. In a YAKINDU statechart, variables and events are contained in so-called _interfaces_. There can be at most one default, unnamed interface plus zero or more named interfaces. In the generated C++ code, these interfaces can be found as internal subclasses of the main state machine class. This outer class' name is derived from the statechart's name while the internal subclasses' names are derived from the respective names of the statechart interfaces.

Let's have a look at the following sample statechart interface declaration of a statechart named _DefaultSM_:

bc. interface Sample:
    var a:boolean
    in event evA:boolean
    out event evB:integer

The generated interface code is shown below in the inner class _SCI_Sample_. Since the statechart's name is _DefaultSM_ the state machine class' name is also _DefaultSM_, to be found in the _DefaultSM.h_ file:

bc.. 

#ifndef DEFAULTSM_H_
#define DEFAULTSM_H_

#include "sc_types.h"
#include "StatemachineInterface.h"

/*! \file Header of the state machine 'DefaultSM'.
*/

class DefaultSM : public StatemachineInterface
{
	
	public:
		
		DefaultSM();
		
		~DefaultSM();
		
		/*! Enumeration of all states */ 
		typedef enum
		{
			main_region_MyState,
			DefaultSM_last_state
		} DefaultSMStates;
		
		//! Inner class for Sample interface scope.
		class SCI_Sample
		{
			
			public:
				/*! Gets the value of the variable 'a' that is defined in the interface scope 'Sample'. */ 
				sc_boolean get_a();
				
				/*! Sets the value of the variable 'a' that is defined in the interface scope 'Sample'. */ 
				void set_a(sc_boolean value);
				
				/*! Raises the in event 'evA' that is defined in the interface scope 'Sample'. */ 
				void raise_evA(sc_boolean value);
				
				/*! Checks if the out event 'evB' that is defined in the interface scope 'Sample' has been raised. */ 
				sc_boolean isRaised_evB();
				
				/*! Gets the value of the out event 'evB' that is defined in the interface scope 'Sample'. */ 
				sc_integer get_evB_value();
				
				
			private:
				friend class DefaultSM;
				sc_boolean a;
				sc_boolean evA_raised;
				sc_boolean evA_value;
				sc_boolean evB_raised;
				sc_integer evB_value;
		};
				
		
		/*! Returns an instance of the interface class 'SCI_Sample'. */
		SCI_Sample* getSCI_Sample();
		
		
		void init();
		
		void enter();
		
		void exit();
		
		void runCycle();
		
		/*!
		* Checks if the state machine is active (until 2.4.1 this method was used for states).
		* A state machine is active if it has been entered. It is inactive if it has not been entered at all or if it has been exited.
		*/
		sc_boolean isActive();
		
		
		/*!
		* Checks if all active states are final. 
		* If there are no active states then the state machine is considered being inactive. In this case this method returns false.
		*/
		sc_boolean isFinal();
		
		
		/*! Checks if the specified state is active (until 2.4.1 the used method for states was calles isActive()). */
		sc_boolean isStateActive(DefaultSMStates state);
	
	private:
	
	
		//! the maximum number of orthogonal states defines the dimension of the state configuration vector.
		static const sc_integer maxOrthogonalStates = 1;
		
		
		DefaultSMStates stateConfVector[maxOrthogonalStates];
		
		sc_ushort stateConfVectorPosition;
		
		SCI_Sample ifaceSample;
		
		// prototypes of all internal functions
		
		void enseq_main_region_MyState_default();
		void enseq_main_region_default();
		void exseq_main_region_MyState();
		void exseq_main_region();
		void react_main_region_MyState();
		void react_main_region__entry_Default();
		void clearInEvents();
		void clearOutEvents();
		
};
#endif /* DEFAULTSM_H_ */

p. A statechart interface is generated as an internal subclass within the state machine class. The subclass' name is derived from the statechart interface's name by prepending the string @SCI_@.

A special case is the unnamed statechart interface: It is generated as the C++ subclass _SCInterface_.

An incoming event _evA:boolean_ is generated as the raise function _raise_evA(boolean value)_. Since the event is of type _boolean_ the function has a _boolean_ parameter.

For an outgoing event _evB:integer_ the functions _isRaised_evB()_ and _get_evB_value()_ are generated. The former can be used to determine whether the event has already been raised by the state machine or not. The latter serves to query the value of the event.

For variables, the code generator creates getter and setter functions, here _sc_boolean get_a()_ and _void set_a(sc_boolean value)_.

The code generator also creates appropriately named getter functions in the enclosing class which can be used to acquire the inner classes, here: _SCI_Sample* getSCI_Sample()_.

The nesting class is the generated state machine source code. It holds instances of the nested interface class implementations and provides them via getter functions. Have a look at (some snippets of) the source code generated for the _Sample_ statechart interface in the source file _DefaultSM.cpp_:

bc.. 
void DefaultSM::SCI_Sample::raise_evA(sc_boolean value)
{
	evA_value = value;
	evA_raised = true;
}

sc_boolean DefaultSM::SCI_Sample::isRaised_evB()
{
	return evB_raised;
}

sc_integer DefaultSM::SCI_Sample::get_evB_value()
{
	return evB_value;
}


sc_boolean DefaultSM::SCI_Sample::get_a()
{
	return a;
}

void DefaultSM::SCI_Sample::set_a(sc_boolean value)
{
	a = value;
}

p. The value of an event can be accessed only if the event has been processed in a run-to-completion step. Otherwise the event could contain an illegal value.

###. FIXME: In Java we have a section "Interface observers". What about a C++ equivalent?



h4(#codegen_cpp_operation_callbacks). Operation callbacks

YAKINDU Statechart Tools support client code operations that can be used by a state machine and are executed as as actions. These operations have to be implemented in the client code in order to make a statechart executable. The figure below shows a sample statechart using an operation:

!images/docu_operationExample.png(Specifying an operation callback in the model)!

p=. Specifying an operation callback in the model

Let's have a look at the additionally generated code for operation support in the _DefaultSM.h_ header file:

bc.. 
				//! Inner class for Sample interface scope operation callbacks.
				class SCI_Sample_OCB
				{
					public:
						virtual ~SCI_Sample_OCB() = 0;
						
						virtual sc_integer myOperation(sc_integer p1, sc_boolean p2) = 0;
				};
				
				/*! Set the working instance of the operation callback interface 'SCI_Sample_OCB'. */
				void setSCI_Sample_OCB(SCI_Sample_OCB* operationCallback);

p. An additional interface _SCI_Sample_OCB_ with the pure virtual function _sc_integer myOperation(sc_integer p1, sc_boolean p2)_ has been generated. This interface has to be implemented, and an instance of the implementing class has to be provided to the state machine via the _setSCI_Sample_OCB(SCI_Sample_OCB* operationCallback)_ function, so that the state machine can use it. The virtual function _sc_integer myOperation(sc_integer p1, sc_boolean p2)_ can be implemented in a new class _OCBImplementation_ with the .h file:

bc.. 
#ifndef OCBIMPLEMENTATION_H_
#define OCBIMPLEMENTATION_H_

#include "DefaultSM.h"

class OCBImplementation : public DefaultSM::SCI_Sample_OCB{
public:
    OCBImplementation();
    virtual ~OCBImplementation();
    sc_integer myOperation(sc_integer p1, sc_boolean p2);
};

#endif /* OCBIMPLEMENTATION_H_ */

p. 

And the implementation in the .cpp file:

bc.. 
#include "OCBImplementation.h"

OCBImplementation::OCBImplementation() {
}

OCBImplementation::~OCBImplementation() {
}

sc_integer OCBImplementation::myOperation(sc_integer p1, sc_boolean p2){
    // Your operation code should be placed here;
    return 0;
}

p. 

Now the OCB must be set by using the _setSCI_Sample_OCB(SCI_Sample_OCB* operationCallback)_ function.

bc.. 
#include "src-gen/DefaultSM.h"
#include "OCBImplementation.h"

int main(int argc, char *argv[]) {
    DefaultSM *defaultSM = new DefaultSM();
    defaultSM->setSCI_Sample_OCB(new OCBImplementation());

    defaultSM->init();
    defaultSM->enter();
    defaultSM->runCycle();
}

p. 

==</div>==
