reference.textile 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128
  1. h1(#YAKINDUStatechartToolsReference). YAKINDU Statechart Tools Reference
  2. h2. Statechart elements
  3. This chapter describes the state chart elements of the YAKINDU SCT 2 editor. The meta model of the YAKINDU SCT 2 is the model of finite state machines. It is based on the view of a system that is defined by a finite number of states. The behavior of such a system is based on its active states. These states are determined by the history of the state machine. Very important are the theoretical models for state machines by Mealy and Moore. Mealy state machines associate actions with transitions. Moore machines associate actions with states (entry, exit). YAKINDU SCT 2 can model both these types.
  4. The YAKINDU SCT 2 meta model is designed similar to the UML statechart meta model with the following differences:
  5. * SCT statecharts are self-contained with interfaces defined by events and variables.
  6. * Core execution semantics are cycle-driven, not event-driven.
  7. ** This allows to process concurrent events.
  8. ** Event-driven behavior can be defined on top.
  9. * Time is an abstract concept for statecharts.
  10. * Time control is delegated to the environment.
  11. The model interpreter and different flavors of generated code are following these same core semantics.
  12. Please refer to the Wikipedia article "UML state machine":http://en.wikipedia.org/wiki/UML_state_machine for more details.
  13. h3(#Regions). Regions
  14. As already mentioned, the YAKINDU statecharts are self-contained. They are organized in regions. Due to this it is possible to organize multiple state machines in different regions and to run them concurrently.
  15. !images/parallelRegions.jpg(Parallel regions)!
  16. h3(#States). States
  17. States are the central elements of a state machine. A state has to be placed inside a region and must have a name that is unique inside this region. During simulation, each state can be active or passive. An active state has actions that are accomplished. Either an action is carried out on entering a state, during active state, or on exit.
  18. h3(#Transitions). Transitions
  19. A transition is the transfer of one state to another. Transitions are diagrammed as arrows. They can have events and actions, but don't need to.
  20. The syntax of events and actions is defined by a "textual description language":#Statechartdescriptionlanguage. Please refer to section "Events":#Events of this documentation for more details! For more details on actions please see chapter "Actions":#ReactionTriggers.
  21. If a state has more than a single outgoing transition without event, then among those transitions the one that has been modeled first will be carried out.
  22. h3(#Initialstateandfinalstate). Initial state and final state
  23. Initial and final states are pseudo states, because the statechart does not rely on them. Pseudo states express characteristics that are impossible to express by simple states.
  24. The initial state is always the first state that becomes active during interpretation or simulation of the state machine. An initial state can have only one outgoing transition and has no incoming ones. Its outgoing transition has no events or actions.
  25. Within a region, only a single initial state is allowed, but each region may have its own initial state.
  26. h3(#Choice). Choice
  27. A choice is also a pseudo state. It can be used to model a conditional path. A choice node divides a transition into multiple parts.
  28. Usually the first transition points towards the choice node. One of the choice's outgoing transitions can carry a condition.
  29. h3(#CompositeState). Composite states
  30. A composite state is a state comprising one or more state machines. These state machines are also organized in regions within the composite state.
  31. Besides the simple composite state YAKINDU SCT knows about two kinds of composite states: orthogonal states and submachine states.
  32. Composite states contain other state machine branches.
  33. h4(#Orthogonalstates). Orthogonal states
  34. In the context of state machines orthogonal states are states that are independent of each other. The presumably most famous example is the keyboard example:
  35. !images/orthogonalState_example.jpg(Orthogonal states)!
  36. h4(#Submachinestates). Subdiagrams
  37. When using composite states, a statechart model often becomes too big to give a comprehensive overview of the whole diagram. Although it is possible to collapse and expand a state's figure compartment, these actions would spoil the diagram layout each time they are executed. Subdiagrams come as a solution.
  38. !images/extract_subdiagram.png(Composite state)!
  39. When the _Extract Subdiagram_ refactoring is executed on a composite state, all containing regions are extracted into a separate diagram. A small decorator in the lower-right corner of the state indicates the existence of such a subdiagram. When you hover with the mouse cursor over this decorator, you'll see a small preview of the subdiagram's content. The refactoring also creates the required entry and exit points for you.
  40. !images/extract_subdiagram2.png(Subdiagram popup window)!
  41. A click on the decorator opens the subdiagram in a separate editor tab. The breadcrumb at the top allows easy navigation throughout the hierachy levels.
  42. !images/extract_subdiagram3.png(Subdiagram editor)!
  43. h3(#ShallowHistory). Shallow history
  44. The shallow history state is a pseudo state that is placed inside regions of composite states. It is used to remember the last active state inside a composite state. This makes it possible to jump back to the remembered state instead of starting at the inner initial state again.
  45. The following example, showing the answering of a questionaire, explains this:
  46. !images/shallowHistory01.jpg(Shallow history [1])!
  47. Particularly interesting in this statechart are the events _checkProgress_ and _goon_. The event _checkProgress_ jumps back to the *init* state while assigning the current progress count to the variable _temp_. The event _goon_ jumps to the shallow history state that was placed inside the composite state.
  48. !images/shallowHistory02.jpg(Shallow history [2])!
  49. !images/shallowHistory03.jpg(Shallow history [3])!
  50. When the _goon_ event is triggered, the most recent active state inside of the composite state *answeringQuestions* is activated again.
  51. h3(#DeepHistory). Deep history
  52. Deep history is similar to shallow history, but more complex. With a deep history the latest state of multiple nested states is remembered.
  53. h2(#Statechartdescriptionlanguage). Statechart description language
  54. A textual description language is used to declare and describe behaviors in a state machine. It is case sensitive.
  55. h3(#Typesystem). Type system
  56. The language has a small integrated type system consisting of the following simple types:
  57. * integer
  58. * real
  59. * boolean
  60. * string
  61. * void
  62. Events and variables can be declared using types:
  63. bc(prettyprint)..
  64. var intVar : integer
  65. var realVar : real
  66. var boolVar : boolean
  67. var stringVar : string
  68. event addInt : integer
  69. event addReal : real
  70. event checkValidity : boolean
  71. event stringEvent : string
  72. event voidEvent : void
  73. h3(#Expressions). Expressions
  74. Expressions in SCT are similar to expressions in other programming languages. The language provides operators for logical expressions, number arithmetic, bitwise arithmetic, and bit shifting.
  75. The type of a logical expression is *boolean*.
  76. h4(#LogicalAND). Logical AND
  77. bc(prettyprint)..
  78. var1 && var2
  79. h4(#LogicalOR). Logical OR
  80. bc(prettyprint)..
  81. var1 || var2
  82. h4(#LogicalNOT). Logical NOT
  83. bc(prettyprint)..
  84. !var1
  85. h4(#Conditionalexpression). Conditional expression
  86. bc(prettyprint)..
  87. var1 ? var2 : 23
  88. h4(#BitwiseXOR). Bitwise XOR
  89. bc(prettyprint)..
  90. var1 ^ var2
  91. h4(#BitwiseOR). Bitwise OR
  92. bc(prettyprint)..
  93. var1 | var2
  94. h4(#BitwiseAND). Bitwise AND
  95. bc(prettyprint)..
  96. var1 & var2
  97. h4(#LogicalRelationsandShiftOperators). Logical Relations and Shift Operators
  98. |less than | @<@ |
  99. |equal or less than | @<=@ |
  100. |greater than | @>@ |
  101. |equal or greater than | @>=@ |
  102. |equal | @==@ |
  103. |not equal | @!=@ |
  104. |shift left | @<<@ |
  105. |shift right | @>>@ |
  106. h4(#Binaryarithmeticoperators). Binary arithmetic operators
  107. |plus | @+@ |
  108. |minus | @-@ |
  109. |multiply | @*@ |
  110. |divide | @/@ |
  111. |modulo | @%@ |
  112. h4(#Unaryarithmeticoperators). Unary arithmetic operators
  113. |positive | @+@ |
  114. |negative | @-@ |
  115. |complement | @~@ |
  116. h3(#Statements). Statements
  117. A statement is one of three kinds:
  118. * assignment
  119. * event raising
  120. * operation call
  121. The language has the following assignment operators:
  122. </p><table><tr><td>simple assignment</td><td><code>=</code></td></tr><tr><td>multiply and assign</td><td><code>*=</code></td></tr><tr><td>divide and assign</td><td><code>/=</code></td></tr><tr><td>calculate modulo and assign</td><td><code>%=</code></td></tr><tr><td>add and assign</td><td><code>+=</code></td></tr><tr><td>subtract and assign</td><td><code>-=</code></td></tr><tr><td>bitshift left and assign</td><td><code><<=</code></td></tr><tr><td>bitshift right and assign</td><td><code>>>=</code></td></tr><tr><td>bitwise AND and assign</td><td><code>&=</code></td></tr><tr><td>bitwise XOR and assign</td><td><code>^=</code></td></tr><tr><td>bitwise OR and assign</td><td><code>|=</code></td></tr></table><p>
  123. ==<!-- FIXME: The following sentences are broken somehow. -->==
  124. An event is raised by calling a method whose name consists of the word _raise_ followed by the event name, e.&nbsp;g. _raiseIncoming_call()_, and if it is an interface event the name of the interface.
  125. An operation is called similar to other programming languages with the operation name and passing concrete parameters. The parameters can be expressions.
  126. h3(#Scopes). Scopes
  127. ==<!-- Start stext_keyword_namespace -->==
  128. h4(#Namespace). Namespace
  129. The language allows to define unique namespaces which can be used to qualify references to the statechart.
  130. bc(prettyprint)..
  131. namespace trafficlights
  132. p. ==<!-- End stext_keyword_namespace -->==
  133. ==<!-- Start stext_keyword_interface -->==
  134. h4(#interfacescope). Interface scope
  135. Declarations in the interface scope are externally visible. They can be shared within the environment.
  136. bc(prettyprint)..
  137. interface NamedInterface:
  138. in event event1
  139. out event event3 : integer
  140. var variable1 : integer
  141. p. ==<!-- End stext_keyword_interface -->==
  142. ==<!-- Start stext_keyword_internal -->==
  143. h4('internalscope). Internal scope
  144. Declarations made in an internal scope are visible to contained states only.
  145. bc(prettyprint)..
  146. internal:
  147. var localVariable1: integer
  148. event localEvent: integer
  149. local event localEvent2
  150. operation localOperation (int1 : integer, int2 : integer): integer
  151. localEvent2 / raise NamedInterface.event3 :
  152. localOperation(valueof(localEvent) , NamedInterface.variable1)
  153. p. ==<!-- End stext_keyword_internal -->==
  154. h3(#Declarations). Declarations
  155. Within scopes events, variables, operations, and local reactions can be declared.
  156. ==<!-- Start stext_keyword_event -->==
  157. h3(#Events). Events
  158. An event in an interface scope has a direction. It is either ingoing or outgoing:
  159. bc(prettyprint)..
  160. interface NamedInterface:
  161. in event event1
  162. out event event2
  163. p. An event in the local scope can carry variables:
  164. bc(prettyprint)..
  165. internal:
  166. event localEvent1 : integer
  167. p. A local event can have a value assignment:
  168. bc(prettyprint)..
  169. internal:
  170. event localEvent1: integer = 25
  171. p. ==<!-- End stext_keyword_event -->==
  172. ==<!-- Start stext_keyword_var -->==
  173. h3(#Variables). Variables
  174. Variables can have different visibilities. They can be visible for the environment:
  175. bc(prettyprint)..
  176. var variable1: real
  177. p. Variables can be *readonly* (constants):
  178. bc(prettyprint)..
  179. var readonly pi: real = 3.1415
  180. p. Variables can be referenced by the environment.
  181. bc(prettyprint)..
  182. var external variable3: integer = 34
  183. p. ==<!-- End stext_keyword_var -->==
  184. ==<!-- Start stext_keyword_const -->==
  185. h3(#Constants). Constants
  186. Variables can be immutable. For this special variable the keyword @const@ is used:
  187. bc(prettyprint)..
  188. const variable1: real
  189. p. ==<!-- End stext_keyword_const -->==
  190. h3(#ReactionTriggers). Reaction Triggers
  191. Actions are key constructs in state machines to model behavior. YAKINDU SCT 2 knows about the following kinds of actions.
  192. ==<!-- Start stext_keyword_after -->==
  193. h4(#after). after
  194. The _after_ trigger specifies a one-shot time event.
  195. After the specified time the reaction is triggered. An _after_ trigger can be used in transitions of states as well as in local reactions of states and statecharts. The specified time starts when the state or statechart is entered.
  196. bc(prettyprint). after 20 s
  197. Structure:
  198. @after@ _@time@_ _@unit@_
  199. The time value may be a literal or an expression that returns an integer value.
  200. The time unit can be:
  201. * ==<!-- Start stext_keyword_s -->== s - seconds ==<!-- End stext_keyword_s -->==
  202. * ==<!-- Start stext_keyword_ms -->== ms - milliseconds ==<!-- End stext_keyword_ms -->==
  203. * ==<!-- Start stext_keyword_us -->== us - microseconds ==<!-- End stext_keyword_us -->==
  204. * ==<!-- Start stext_keyword_ns -->== ns - nanoseconds ==<!-- End stext_keyword_ns -->==
  205. p. ==<!-- End stext_keyword_after -->==
  206. ==<!-- Start stext_keyword_every -->==
  207. h4(#every). every
  208. The _every_ trigger specifies periodic time events.
  209. The reaction is triggered recurrently after each passing of the specified period of time. An _every_ trigger can be used in transitions as well as in local reactions of states and statecharts. The specified period of time starts when the state or statechart is entered and repeats periodically.
  210. bc(prettyprint). every 200 ms
  211. Structure:
  212. @every@ _@time@_ _@unit@_
  213. The time value may be a literal or an expression that returns an integer value.
  214. The time unit can be:
  215. * s - seconds
  216. * ms - milliseconds
  217. * us - microseconds
  218. * ns - nanoseconds
  219. ==<!-- End stext_keyword_every -->==
  220. ==<!-- Start stext_keyword_always -->==
  221. h4(#always). always
  222. This trigger is always true and enables a reaction to be executed in every run-to-completion step (RTC). It is equivalent to _oncycle_.
  223. ==<!-- End stext_keyword_always -->==
  224. ==<!-- Start stext_keyword_default -->==
  225. ==<!-- Start stext_keyword_else -->==
  226. h4(#defaultelse). default, else
  227. The _default_ trigger is equivalent to the _else_ trigger. It is intended to be used for the outgoing transitions of _choice_ pseudo states to make sure that there is always an outgoing transition that can be taken. The _default_ trigger can only be be used in transitions and implies the lowest evaluation priority for that transition.
  228. ==<!-- End stext_keyword_else -->==
  229. ==<!-- End stext_keyword_default -->==
  230. ==<!-- Start stext_keyword_entry -->==
  231. h4(#entry). entry
  232. An _entry_ trigger marks actions that are carried out on entering a state or state machine.
  233. ==<!-- End stext_keyword_entry -->==
  234. ==<!-- Start stext_keyword_exit -->==
  235. h4(#exit). exit
  236. An _exit_ trigger marks actions that are carried out on exiting a state or state machine.
  237. ==<!-- End stext_keyword_exit -->==
  238. ==<!-- Start stext_keyword_oncycle -->==
  239. h4(#oncycle). oncycle
  240. The _oncycle_ trigger is always true and enables a reaction to be executed in every run-to-completion step (RTC). It is equivalent to _always_.
  241. ==<!-- End stext_keyword_oncycle -->==
  242. ==<!-- Start stext_keyword_operation -->==
  243. h3(#Operations). Operations
  244. Operations can have none, one or multiple parameters. A parameter is declared with a name and a type. An operation may have a single return type similar to Java.
  245. bc(prettyprint)..
  246. operation localOperation (xValue : integer, yValue : integer):integer
  247. p.
  248. ==<!-- End stext_keyword_operation -->==
  249. h3(#BuildInFunctions). Build-in functions
  250. ==<!-- Start stext_keyword_valueof -->==
  251. h4(#valueofevent). valueof(event)
  252. ==<!-- FIXME: Clarify/elaborate the meaning of the following sentence: -->==
  253. Returns the value of an valued event that it passed to the function as parameter.
  254. bc(prettyprint)..
  255. myVar = valueof(myEvent)
  256. p.
  257. ==<!-- End stext_keyword_valueof -->==
  258. ==<!-- Start stext_keyword_as -->==
  259. h4(#as). as
  260. Casts a variable. The following example casts a literal from integer to real.
  261. bc(prettyprint)..
  262. myReal = 12 as real
  263. p.
  264. ==<!-- End stext_keyword_as -->==
  265. ==<!-- Start stext_keyword_active -->==
  266. h4(#activestate). active(state)
  267. Returns _true_ if a state is active and _false_ otherwise.
  268. bc(prettyprint)..
  269. myBool = active(StateA)
  270. p.
  271. ==<!-- End stext_keyword_active -->==
  272. h3(#LocalReactions). Local reactions
  273. Local reactions describe the internal behavior of a state. So they have internal scope. A local reaction is declared as follows:
  274. bc(prettyprint)..
  275. LocalReaction: ReactionTrigger '/' ReactionEffect ('#' ReactionProperties)?
  276. ReactionTrigger: (Event ("," Event )* (=> '[' Expression ']')?) | '[' Expression ']'
  277. ReactionEffect: Statement (';' Statement )* (';')?
  278. Statement: Assignment | EventRaising | OperationCall
  279. ReactionProperties: (EntryPoint | ExitPoint)*
  280. p. Within a local reaction an interface event can be raised:
  281. bc(prettyprint)..
  282. internal:
  283. localEvent1 / raise NamedInterface.event3 : localOperation (valueof(localEvent), NamedInterface.variable1);
  284. p. A local reaction can have a priority value. The latter is defined by appending the character @#@ and the numeric priority value to the local reaction's definition. Examples:
  285. ==<!-- FIXME: Describe the meaning of priorities! -->==
  286. bc(prettyprint#GeneratorFeatures)..
  287. localEvent2 / NamedInterface.variable2 += 3; #1
  288. localEvent3 / NamedInterface.variable4 += 2.0; #2
  289. h2(#Codegeneration). Code generation
  290. h3. SGen generator features
  291. All generators can be customized by a generator model. This is a textual model in a file, specifying generator features, i.e. the outlet path. The following screenshot shows an sample configuration for the Java code generator.
  292. To get started with the generator model, YAKINDU Statechart Tools includes a wizard that creates a basic configuration file with default values.
  293. !images/sGenEditor.png(SGen generator model with default values)!
  294. ==<!-- FIXME: Explain what a "builder" is! -->==
  295. The generator model is associated with the builder. If _Project → Build Automatically_ is checked, the generator automatically creates its output files for each modification the user makes to the statechart model. Below the specific customizing features of the generator models are explained.
  296. The following section describes the *Core Features* which are available for all code generators:
  297. ==<!-- Start sgen_feature_outlet -->==
  298. h4(#Outlet). Outlet
  299. The *Outlet* feature specifies target project and target folder for the generated artifacts. It is a _required_ feature and has the following parameters:
  300. # __targetProject__ (String, required): The project to store the generated artifacts to.
  301. # __targetFolder__ (String, required): The folder to store the generated artifacts to. If a library folder is given, only the dynamic (i.e. model dependent artifacts) are generated into the target folder, if not all generated artifacts will be generated into it. All artifacts in this folder will be overwritten during re-generation.
  302. # __libraryTargetFolder__ (String, optional): The folder to store the static (i.e. model independent artifacts) to. In case this is not specified, all artifacts will be generated into the target folder. All artifacts in this folder will be preserved during re-generation.
  303. Sample configuration:
  304. bc(prettyprint)..
  305. feature Outlet {
  306. targetProject = "SampleProject"
  307. targetFolder = "src-gen"
  308. libraryTargetFolder = "src"
  309. }
  310. p. ==<!-- End sgen_feature_outlet -->==
  311. ==<!-- Start sgen_feature_licenseheader -->==
  312. h4(#LicenseHeader). LicenseHeader
  313. The *LicenseHeader* feature specifies the license text that is to be added as a header to the generated artifacts. It is an *optional* feature and has the following parameters:
  314. # __licenseText__ (String, required): License text to be added as a file header
  315. Sample configuration:
  316. bc(prettyprint)..
  317. feature LicenseHeader {
  318. licenseText = "Copyright (c) 2012 committers of YAKINDU and others."
  319. }
  320. p. ==<!-- End sgen_feature_licenseheader -->==
  321. ==<!-- Start sgen_feature_functioninlining -->==
  322. h4(#FunctionInlining). FunctionInlining
  323. The *FunctionInlining* feature enables the inlining of expressions instead of generating separate functions or methods. This might reduce the readability of the generated code, but increases performance, because less operation calls are necessary.
  324. It is an *optional* feature and has the following parameters:
  325. # __inlineReactions__ (Boolean, optional): inlines the expression for reactions
  326. # __inlineEntryActions__ (Boolean, optional): inlines the expression for entry actions
  327. # __inlineExitActions__ (Boolean, optional): inlines the expression for exit actions
  328. # __inlineEnterSequences__ (Boolean, optional): inlines the expression for enter sequences
  329. # __inlineExitSequences__ (Boolean, optional): inlines the expression for exit sequences
  330. # __inlineChoices__ (Boolean, optional): inlines the expression for choices
  331. # __inlineEnterRegion__ (Boolean, optional): inlines the expression for enter regions
  332. # __inlineExitRegion__ (Boolean, optional): inlines the expression for exit regions
  333. # __inlineEntries__ (Boolean, optional): inlines the expression for entries
  334. Sample configuration:
  335. bc(prettyprint)..
  336. feature FunctionInlining {
  337. inlineChoices = false
  338. inlineEnterRegion = true
  339. inlineEntries = true
  340. }
  341. p. ==<!-- End sgen_feature_functioninlining -->==
  342. ==<!-- Start sgen_feature_debug -->==
  343. h4(#Debug). Debug
  344. The *Debug* feature dumps the execution model to the target folder as an XMI model. It is an *optional* feature and has the following parameter:
  345. # __dumpSexec__ (Boolean, required): dumps the execution model as XMI model
  346. Sample configuration:
  347. bc(prettyprint)..
  348. feature Debug {
  349. dumpSexec = true
  350. }
  351. p. ==<!-- End sgen_feature_debug -->==
  352. h3(#JavaGeneratorFeatures). Java generator features
  353. ==<!-- Start sgen_feature_naming -->==
  354. h4. Naming feature
  355. The *Naming* feature allows the configuration of package names as well as class name prefix / suffix.
  356. It is an *optional* feature and has the following parameters:
  357. # __basePackage__ (Boolean, required): The package to create for the generated java classes
  358. # __implementationSuffix__ (Boolean, optional): The suffix for the implementing classes
  359. Sample configuration:
  360. bc(prettyprint)..
  361. feature Naming {
  362. basePackage = "org.yakindu.sct"
  363. implementationSuffix = "Impl"
  364. }
  365. p. ==<!-- End sgen_feature_naming -->==
  366. ==<!-- Start sgen_feature_synchronizedwrapper -->==
  367. h4. SynchronizedWrapper
  368. Add documentation for synchronized wrapper here.
  369. p. ==<!-- End sgen_feature_synchronizedwrapper -->==
  370. ==<!-- Start sgen_feature_runnablewrapper -->==
  371. h4. RunnableWrapper
  372. Generates a runnable wrapper for the state machine. This feature generates an additional Java class providing a thread-safe wrapper for the generated state machine implementation. In addition to the specific state machine interface it implements the __Runnable__ interface and can be executed in a thread. It implements an event queue and event-driven execution semantics. As the wrapper adds thread safety any number of client threads may call the state machine.
  373. It is an *optional* feature and has the following parameters:
  374. # __namePrefix__ (String, optional): prefix of the implementing class' name
  375. # __nameSuffix__ (String, optional): suffix of the implementing class' name
  376. Sample configuration:
  377. ==<!-- FIXME: The namePrefix in the example below does not have a trailing dot. Is this correct? -->==
  378. bc(prettyprint)..
  379. feature RunnableWrapper {
  380. namePrefix = ""
  381. nameSuffix = "Runnable"
  382. }
  383. p. ==<!-- End sgen_feature_runnablewrapper -->==
  384. ==<!-- Start sgen_feature_generalfeatures -->==
  385. h4(#GeneralFeatures). GeneralFeatures
  386. The *GeneralFeatures* feature allows to configure additional services to be generated along with the state machine. Per default, all parameters are __false__. It is an *optional* feature and has the following parameters:
  387. ==<!-- # __EventBasedStatemachine__ (Boolean, optional): enables/disables the generation of a cycle based state machine implementation -->==
  388. # __InterfaceObserverSupport__ (Boolean, optional): enables/disables the generation of listener interfaces for the state machine
  389. # __RuntimeService__ (Boolean, optional): enables/disables the generation of a runtime service that triggers the run cycle of a cycle-based state machine
  390. # __TimerService__ (Boolean, optional): enables/disables the generation of a timer service implementation using __java.util.Timer__
  391. ==<!-- # __GenericInterfaceSupport__ (Boolean, optional): enables/disables the generation of generic interfaces -->==
  392. ==<!-- # __StatemachineFactorySupport__ (Boolean, optional): enables/disables the generation of a factory class -->==
  393. Sample configuration:
  394. bc(prettyprint)..
  395. feature GeneralFeatures {
  396. InterfaceObserverSupport = true
  397. RuntimeService = true
  398. TimerService = true
  399. }
  400. p. ==<!-- End sgen_feature_generalfeatures -->==
  401. h3(#CGeneratorFeatures). C/C++ generator features
  402. ==<!-- Start sgen_feature_identifiersettings -->==
  403. h4. IdentifierSettings
  404. The *IdentifierSettings* feature allows the configuration of module names and identifier character length:
  405. # __moduleName__ (String, optional): name for header and implementation, default: statechart name
  406. # __statemachinePrefix__ (Boolean, optional): prefix which is prepended to function, state, and type names.
  407. # __maxIdentifierLength__ (Integer, optional): maximum number of characters of an identifier, default: 31 characters, which is complying with the ANSI C99 standard.
  408. # __separator__ (String, optional): character to replace whitespace and otherwise illegal characters in manes.
  409. Sample configuration:
  410. bc(prettyprint)..
  411. feature IdentifierSettings {
  412. moduleName = "MyStatechart"
  413. statemachinePrefix = "myStatechart"
  414. maxIdentifierLength = 31
  415. separator = "_"
  416. }
  417. p. ==<!-- End sgen_feature_identifiersettings -->==
  418. ==<!-- Start sgen_feature_tracing -->==
  419. h4. Tracing
  420. The *Tracing* feature allows to enable generation of tracing callback functions:
  421. # __enterState__ (Boolean, optional): whether to generate a callback that is used to notify about 'state enter' events.
  422. # __exitState__ (Boolean, optional): whether to generate a callback that is used to notify about 'state exit' events.
  423. Sample configuration:
  424. bc(prettyprint)..
  425. feature Tracing {
  426. enterState = true
  427. exitState = true
  428. }
  429. p. ==<!-- End sgen_feature_tracing -->==
  430. ==<!-- Start sgen_feature_generatoroptions -->==
  431. h4. GeneratorOptions
  432. The *GeneratorOptions* feature allows change the behavior of the C++ generator:
  433. # __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.
  434. # __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.
  435. Sample configuration:
  436. bc(prettyprint)..
  437. feature GeneratorOptions {
  438. innerFunctionVisibility = "protected"
  439. staticOperationCallback = true
  440. }
  441. p. ==<!-- End sgen_feature_generatoroptions -->==
  442. ==<!-- Start sgen_feature_junitwrapper -->==
  443. h4. JUnitWrapper
  444. Using the *JUnitWrapper* feature it is possible to create JUnit tests that will run the generated gtests.
  445. # __WrapToJUnit__ (Boolean): This parameter determines whether a JUnit wrapper test is to be generated __(true)__ or not __(false)__.
  446. Sample configuration:
  447. bc(prettyprint)..
  448. feature JUnitWrapper {
  449. WrapToJUnit = "false"
  450. }
  451. p. ==<!-- End sgen_feature_junitwrapper -->==
  452. h3. Custom code generators
  453. h4(#CreatingCustomCodeGenerators). Creating custom code generators
  454. YAKINDU Statechart Tools provide a rich feature set to support custom code generators out of the box. These code generators can be either written in Java, "Xtend":http://www.eclipse.org/xtend/, or "Xpand":http://www.eclipse.org/modeling/m2t/?project=xpand.
  455. h5(#WritingacustomcodegeneratorwithXtend2Java). Writing a custom code generator with Xtend2/Java
  456. First, you have to create a new Xtend2 generator project. Click __File → New → Other... → YAKINDU → YAKINDU Xtend2/Java Generator Project__ to create a new Xtend2 generator project.
  457. !images/xtendGenerator.png(Creating an Xtend2 generator project)!
  458. The wizard asks for a *Project name* and the name of the *Generator class*, which has to be the fully-qualified class name. If you check the *Use Xtend* checkbox, the generator class will initially be created as an "Xtend":http://www.eclipse.org/xtend/ class. Otherwise, Java will be used for the generator.
  459. The check box *Configure for Plugin Export* adds all required extension point registrations to the new project for exporting it as a plugin. The generator model can refer to the new generator plugin via its unique *Generator ID*. If you want to contribute custom generator features for your code generator, check the *Create Feature Library* check box.
  460. After clicking on *Finish* a new project is created in your workspace. All required plugin dependencies and extension points are registered and you can start to write your code generator based on the ExecutionFlow meta model [Link].
  461. h4(#ExecutingacustomXtend2Javacodegenerator). Executing a custom Xtend2/Java code generator
  462. YAKINDU Statechart Tools provide a convenient way to execute your generator while you are developing it.
  463. For this, you have to create a new *generator model* with the generator ID *yakindu::generic*, either by using the *New Statechart Generator Model* wizard or by simply creating a new text file with the file extension @.sgen@. The feature described below allows to configure your code generator.
  464. ==<!-- Start sgen_feature_generator -->==
  465. h5(#Generator). Generator
  466. The *Generator* feature allows to configure a custom code generator located in the workspace and written in Java or in another JVM language. It is a *required* feature and has the following parameters:
  467. # __generatorProject__ (String, required): the name of the generator project
  468. # __generatorClass__ (String, required): the fully-qualified name of the code generator class
  469. # __configurationModule__ (String, optional): the fully-qualified class name of a Guice module to configure the code generator
  470. Sample configuration:
  471. bc(prettyprint)..
  472. feature Generator {
  473. generatorProject = "org.yakindu.sct.mygenerator"
  474. generatorClass = "org.yakindu.sct.MyGenerator"
  475. }
  476. p. ==<!-- End sgen_feature_generator -->==
  477. h4(#ExecutingacustomXpandcodegenerator). Executing a custom Xpand code generator
  478. In order to execute an Xpand-based custom code generator, you have to create a new *Generator Model* with the generator ID *yakindu::xpand*, either by using the *New Statechart Generator Model* wizard or by simply creating a new text file with the file extension *.sgen*. The following feature allows to configure your code generator.
  479. ==<!-- Start sgen_feature_template -->==
  480. h5(#Template). Template
  481. The *Generator* feature allows to configure a custom code generator located in the workspace and written in Java or in another JVM language. It is a *required* feature and has the following parameters:
  482. # __templateProject__ (String, required): the name of the generator project
  483. # __templatePath__ (String, required): the fully-qualified template path of the main template
  484. Sample configuration:
  485. bc(prettyprint)..
  486. feature Template {
  487. templateProject = "ExampleProject"
  488. templatePath = "org::yakindu::sct::generator::xpand::Main::main"
  489. }
  490. p. ==<!-- End sgen_feature_template -->==
  491. h2(#APISpecification). API specifications of the generated code
  492. The explanations below are using the _TrafficLight_ sample state machine to describe the API specifications of the code generated by the YAKINDU C and Java code generators. The image below is showing the statechart. It models a pedestrian crossing with push-button operated traffic lights ("pelican crossing").
  493. !(img-rounded shadowed#SpecJava)images/TrafficLight.png(The traffic light model)!
  494. h3(#JavaSpec). Specifications of Java code
  495. You can checkout the Java sample project _"org.yakindusct.examples.trafficlight":https://github.com/Yakindu/statecharts/tree/master/examples/org.yakindu.sct.examples.trafficlight_ from the "YAKINDU Statechart Tools GitHub repository":https://github.com/Yakindu/statecharts. The Java 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 SWT.
  496. To execute the Java example, run the file _CrossingDemoCycleBased.java_ as "Java Application" from the Eclipse _Run As_ context menu.
  497. h4(#JavaGeneratedCode). Generated code files
  498. Generally you will find generated code at the places specified in the SGen model, see <a href="#Outlet">section "Outlet"</a> for details.
  499. In the case of the traffic light example, you will find the generated code in the _src-gen_ folder.
  500. The package _org.yakindu.sct.examples.trafficlight.cyclebased_ contains the general state machine interfaces and classes. They are needed by each particular state machine and are independend from concrete ones.
  501. h4. The state machine interface
  502. Each generated state machine implements the @IStatemachine@ interface:
  503. bc(prettyprint)..
  504. package org.yakindu.sct.examples.trafficlight.cyclebased;
  505. /**
  506. * Basic interface for state machines.
  507. */
  508. public interface IStatemachine {
  509. /**
  510. * Initializes the state machine. Use to init internal variables etc.
  511. */
  512. public void init();
  513. /**
  514. * Enters the state machine. Sets the state machine in a defined state.
  515. */
  516. public void enter();
  517. /**
  518. * Exits the state machine. Leaves the state machine with a defined state.
  519. */
  520. public void exit();
  521. /**
  522. * Start a run-to-completion cycle.
  523. */
  524. public void runCycle();
  525. }
  526. h5. Fundamental statechart methods
  527. The generated code contains fundamental methods to initialize, enter, and exit a state machine, as well as a method to start a run-to-completion step.
  528. The @IStatemachine@ interface specifies the four methods @init()@, @enter()@, @exit()@, and @runCycle()@.
  529. * The @init()@ method 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 initialized variables, these initializations are also done in the @init()@ method.
  530. * The @enter()@ method must be called to enter the state machine. It brings the state machine to a well-defined state.
  531. * The @exit()@ method 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.
  532. * The @runCycle()@ method 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:
  533. # Clear list of outgoing events.
  534. # Check whether events have occurred which are leading to a state change.
  535. # If a state change has to be done:
  536. ## Execute exit actions of the present state.
  537. ## Save history state, if necessary.
  538. ## Make the new state active. ==<!-- FIXME: We should also make the old state inactive, shouldn't we? -->==
  539. ## Execute entry actions of the new state.
  540. # Clear list of incoming events.
  541. ==<!-- h5. Variable and event access -->==
  542. ==<!-- Do we need some equivalent to the C section here? Here's the C text: -->==
  543. ==<!-- The getters and setters for each variable and event are also contained in the header file. The method names are matching the following pattern: _statechart_name_<code>Iface</code>_interface_name_@_@[ <code>set</code> | <code>get</code> | <code>raise</code> ]@_@[ _variable_name_ | _event_name_ ]. For example, the getter of the variable _red_ of the _pedestrian_ interface is named @trafficLightWaitingIfacePedestrian_get_red(TrafficLightWaiting* handle)@. -->==
  544. h4. Time-controlled state machines
  545. If a statechart uses timing functionality, additional classes are generated.
  546. The traffic light example uses timing funtionality, namely _after_ clauses. To support time-controlled behavior, the interfaces @ITimerCallback@ and @ITimer@ are generated. Like @IStatemachine@, they are independend of any particular state machine and are generated in the _libraryTargetFolder_ directory, if specified. See <a href="#Outlet">section "Outlet"</a> for details.
  547. The generated state machine class implements the @ITimerCallback@ and has a property _timer_ of type @ITimer@. The client code must provide an @ITimer@ implementation to the state machine by calling the latter's @setTimer()@ method.
  548. Here's an example showing how to create a new instance of the state machine (here: class @MyTimedStatemachine@), create a new instance of a timer (here: class @MyTimer@), set the latter on the former, and start the state machine by entering it:
  549. bc(prettyprint)..
  550. MyTimedStatemachine sm = new MyTimedStatemachine();
  551. sm.setTimer(new MyTimer());
  552. sm.enter(); // Enter the state machine
  553. p. Timer functions generally depend on the hardware target used, therefore the proper time handling has to be implemented by the developer. In principle, for each hardware target a dedicated timer service class implementing the @ITimer@ interface has to be developed.
  554. h4. Default timer implementation
  555. However, upon request the Java code generator can create a default implementation of the @ITimer@ interface, and in many cases it will be sufficient. This implementation is based on @java.util.Timer@ and @java.util.TimerTask@ and should be compatible with the Oracle JVM or the OpenJDK JVM.
  556. To generate the default timer service class, set the _TimerService_ feature in the SGen model to _true_. Example:
  557. bc(prettyprint)..
  558. GeneratorModel for yakindu::java {
  559. statechart MyStateMachine {
  560. /* … */
  561. feature GeneralFeatures {
  562. TimerService = true
  563. }
  564. }
  565. }
  566. p. The generated class is named @TimerService@ and looks like this:
  567. bc(prettyprint)..
  568. package org.yakindu.scr;
  569. import java.util.ArrayList;
  570. import java.util.List;
  571. import java.util.Timer;
  572. import java.util.TimerTask;
  573. /**
  574. * Default timer service implementation.
  575. *
  576. */
  577. public class TimerService implements ITimer {
  578. private final Timer timer = new Timer();
  579. private final List<TimeEventTask> timerTaskList = new ArrayList<TimeEventTask>();
  580. /**
  581. * Timer task that reflects a time event. It's internally used by
  582. * {@link TimerService}.
  583. *
  584. */
  585. private class TimeEventTask extends TimerTask {
  586. private ITimerCallback callback;
  587. int eventID;
  588. /**
  589. * Constructor for a time event.
  590. *
  591. * @param callback
  592. * : Set to {@code true} if event should be repeated
  593. * periodically.
  594. *
  595. * @param eventID
  596. * : Index position within the state machine's timeEvent
  597. * array.
  598. */
  599. public TimeEventTask(ITimerCallback callback, int eventID) {
  600. this.callback = callback;
  601. this.eventID = eventID;
  602. }
  603. public void run() {
  604. callback.timeElapsed(eventID);
  605. }
  606. public boolean equals(Object obj) {
  607. if (obj instanceof TimeEventTask) {
  608. return ((TimeEventTask) obj).callback.equals(callback)
  609. && ((TimeEventTask) obj).eventID == eventID;
  610. }
  611. return super.equals(obj);
  612. }
  613. }
  614. public void setTimer(final ITimerCallback callback, final int eventID,
  615. long time, boolean isPeriodic) {
  616. // Create a new TimerTask for given event and store it.
  617. TimeEventTask timerTask = new TimeEventTask(callback, eventID);
  618. timerTaskList.add(timerTask);
  619. // start scheduling the timer
  620. if (isPeriodic) {
  621. timer.scheduleAtFixedRate(timerTask, time, time);
  622. } else {
  623. timer.schedule(timerTask, time);
  624. }
  625. }
  626. public void unsetTimer(ITimerCallback callback, int eventID) {
  627. int index = timerTaskList.indexOf(new TimeEventTask(callback, eventID));
  628. if (index != -1) {
  629. timerTaskList.get(index).cancel();
  630. timer.purge();
  631. timerTaskList.remove(index);
  632. }
  633. }
  634. /**
  635. * Cancel timer service. Use this to end possible timing threads and free
  636. * memory resources.
  637. */
  638. public void cancel() {
  639. timer.cancel();
  640. timer.purge();
  641. }
  642. }
  643. h4. Timer service
  644. A timer service must implement the @ITimer@ interface and must be able to maintain a number of time events and the timers associated with them. A time event is identified by a numeric ID.
  645. If suitable, an application can use the default timer service class @TimerService@, see <a href="#Defaulttimerimplementation">"Default timer implementation"</a> for details.
  646. The @ITimer@ interface looks like this:
  647. bc(prettyprint)..
  648. package org.yakindu.scr;
  649. /**
  650. * Interface a timer has to implement. Use to implement your own timer
  651. * service.
  652. *
  653. */
  654. public interface ITimer {
  655. /**
  656. * Starts the timing for a given time event id.
  657. *
  658. * @param callback
  659. * : The target callback where the time event has to be raised.
  660. *
  661. * @param eventID
  662. * : The eventID the timer should use if timed out.
  663. *
  664. * @param time
  665. * : Time in milliseconds after the given time event should be
  666. * triggered
  667. *
  668. * @param isPeriodic
  669. * : Set to true if the time event should be triggered periodically
  670. */
  671. public void setTimer(ITimerCallback callback, int eventID, long time, boolean isPeriodic);
  672. /**
  673. * Unset a time event.
  674. *
  675. * @param callback
  676. * : The target callback for which the time event has to be unset.
  677. *
  678. * @param eventID
  679. * : The time event id.
  680. */
  681. public void unsetTimer(ITimerCallback callback, int eventID);
  682. }
  683. h5. Method setTimer
  684. p. A state machine calls the @setTimer(ITimerCallback callback, int eventID, long time, boolean isPeriodic)@ method to tell the timer service that it has to start a timer for the given _eventID_. The _time_ parameter specifies the number of milliseconds until the timer expires. When this period of time has elapsed, the timer service must raise the time event by calling the method @public void timeElapsed(int eventID)@ on the @ITimerCallback@ specified by the _callback_ parameter, i.&nbsp;e. usually the state machine.
  685. It is important to keep the execution of the @setTimer()@ method short and use it only to start a timer thread, a hardware timer interrupt, or the like. Avoid any time-consuming operations like extensive computations, @Thread.sleep(…)@, waiting, etc. Otherwise the state machine execution might hang within the timer service or might not show the expected runtime behavior.
  686. If the parameter _isPeriodic_ is _false_, the timer service raises the time event only once. If _isPeriodic_ is _true_, the timer service raises the time event every _time_ milliseconds.
  687. h5. Method unsetTimer
  688. If the state machine calls the @unsetTimer(ITimerCallback callback, int eventID)@ method the timer service must unset the timer for the given _eventID_, i.&nbsp;e. the time event will not be raised.
  689. h4. Raising time events on a state machine
  690. If a statechart is using time events, the generated Java state machine class not only implements the @IStatemachine@ interface, but it also implements the @ITimerCallback@ interface. @ITimerCallback@ is defined as follows. It specifies a single method: @public void timeElapsed(int eventID)@.
  691. bc(prettyprint)..
  692. package org.yakindu.scr;
  693. /**
  694. * Interface for state machines which use timed event triggers.
  695. */
  696. public interface ITimerCallback {
  697. /**
  698. * Callback method if a time event occurred.
  699. *
  700. * @param eventID
  701. * :The id of the occurred event.
  702. */
  703. public void timeElapsed(int eventID);
  704. }
  705. h5. Method timeElapsed
  706. It is the timer service's responsibility to actually raise a time event on a state machine. To do so, the timer service calls the state machine's @timeElapsed()@ method and supplies the time event's _eventID_ as a parameter. The state machine recognizes the time event and will process it during the next run cycle.
  707. You can conclude that in order to process time events without too much latency, the runtime environment has to call the state machine's @runCycle()@ method 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()@ method with a frequency of once per 1000 ms only, the event will quite likely not be processed at the correct points in time.
  708. h4(#RuntimeService). Runtime service
  709. The @RuntimeService@ class maintains all state machines that are expected to execute run-to-completion steps periodically. A client application can retrieve the @RuntimeService@ singleton using @RuntimeService.getInstance()@. It can then pause, resume or cancel all state machines that are poised to run at a specified intervall.
  710. h4(#JavaInterVar). Accessing interfaces, variables and events
  711. 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 Java code, these interfaces can be found as inner interface of the interface specifying the state machine. The outer interface's name is derived from the statechart's name while the inner interfaces' names are derived from the respective names of the statechart interfaces.
  712. Let's have a look at the following sample statechart interface declaration:
  713. bc(prettyprint)..
  714. interface Sample:
  715. var a:boolean
  716. in event evA:boolean
  717. out event evB:integer
  718. p. The generated interface code looks like this:
  719. bc(prettyprint)..
  720. import org.yakindu.scr.IStatemachine;
  721. import org.yakindu.scr.ITimerCallback;
  722. public interface IDefaultSMStatemachine extends ITimerCallback, IStatemachine {
  723. public interface SCISample {
  724. public void raiseEvA(boolean value);
  725. public boolean isRaisedEvB();
  726. public long getEvBValue();
  727. public boolean getA();
  728. public void setA(boolean value);
  729. }
  730. public SCISample getSCISample();
  731. }
  732. p. A statechart interface is generated as an inner Java interface within the state machine interface. The Java interface's name is derived from the statechart interface's name by prepending the string @SCI@.
  733. A special case is the unnamed statechart interface: It is generated as the Java interface @SCInterface@.
  734. An incoming event _evA:boolean_ is generated as the raise method @raiseEvA(boolean value)@. Since the event is of type _boolean_ the method has a _boolean_ parameter.
  735. For an outgoing event _evB:integer_ the methods @boolean isRaisedEvB()@ and @long getEvBValue()@ 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.
  736. For variables, the code generator creates getter and setter methods, here @boolean getA()@ and @void setA(boolean value)@.
  737. The code generator also creates appropriately named getter methods in the enclosing interface which can be used to acquire the nested interfaces, here: @SCISample getSCISample()@.
  738. The nesting interface is implemented by the generated state machine source code. Each nested interface is implemented as an internal class of the state machine class. The latter holds instances of the nested interface implementations and provides them via getter methods. Have a look at (some snippets of) the source code generated for the _Sample_ interface:
  739. bc(prettyprint)..
  740. import org.yakindu.scr.ITimer;
  741. public class DefaultSMStatemachine implements IDefaultSMStatemachine {
  742. protected class SCISampleImpl implements SCISample {
  743. private boolean evA;
  744. private boolean evAValue;
  745. public void raiseEvA(boolean value) {
  746. evA = true;
  747. evAValue = value;
  748. }
  749. protected boolean getEvAValue() {
  750. if (!evA)
  751. throw new IllegalStateException("Illegal event value acces. Event EvA is not raised!");
  752. return evAValue;
  753. }
  754. private boolean evB;
  755. private long evBValue;
  756. public boolean isRaisedEvB() {
  757. return evB;
  758. }
  759. protected void raiseEvB(long value) {
  760. evB = true;
  761. evBValue = value;
  762. }
  763. public long getEvBValue() {
  764. if (!evB)
  765. throw new IllegalStateException("Illegal event value acces. Event EvB is not raised!");
  766. return evBValue;
  767. }
  768. private boolean a;
  769. public boolean getA() {
  770. return a;
  771. }
  772. public void setA(boolean value) {
  773. this.a = value;
  774. }
  775. protected void clearEvents() {
  776. evA = false;
  777. }
  778. protected void clearOutEvents() {
  779. evB = false;
  780. }
  781. }
  782. protected SCISampleImpl sCISample;
  783. public SCISample getSCISample() {
  784. return sCISample;
  785. }
  786. /* … */
  787. }
  788. p. The value of an event can be accessed only if the event has been processed in a run-to-completion step. Otherwise an @IllegalStateException@ will be thrown.
  789. h4(#JavaInterfaceObservers). Interface observers
  790. If the general feature _InterfaceObserverSupport_ is enabled in the SGen model, the generated interfaces will support the registration of observers.
  791. Enabling the _InterfaceObserverSupport_ feature looks like this in the _.sgen_ file:
  792. bc(prettyprint)..
  793. feature GeneralFeatures {
  794. InterfaceObserverSupport = true
  795. }
  796. p. Now the generated code has additional features:
  797. bc(prettyprint)..
  798. package org.yakindu.scr.defaultsm;
  799. import java.util.List;
  800. import org.yakindu.scr.IStatemachine;
  801. import org.yakindu.scr.ITimerCallback;
  802. public interface IDefaultSMStatemachine extends ITimerCallback, IStatemachine {
  803. public interface SCISample {
  804. public void raiseEvA(boolean value);
  805. public boolean isRaisedEvB();
  806. public long getEvBValue();
  807. public boolean getA();
  808. public void setA(boolean value);
  809. public List<SCISampleListener> getListeners();
  810. }
  811. public interface SCISampleListener {
  812. public void onEvBRaised(long value);
  813. }
  814. public SCISample getSCISample();
  815. }
  816. p. An additional listener interface is generated, here @SCISampleListener@. It contains a callback method for each outgoing event. Here it is a single one: @void onEvBRaised(long value)@.
  817. The client code has to provide an implementation of the listener interface. A listener method gets called by the state machine when it raises an outgoing event.
  818. To register or unregister a listener, use the @getListeners()@ method of the nesting interface. This method returns a @java.util.List@ parameterized with the appropriate listener type. Initially this list is empty. Add or remove listeners as needed.
  819. A callback method specified by the listener interface should complete its operations quickly, because otherwise the state machine execution might be delayed for too long, potentially leading to unexpected runtime behavior.
  820. h4(#JavaOperationCallbacks). Operation callbacks
  821. YAKINDU Statechart Tools support *operations* that are executed by a state machine as actions, but are implemented by client-side code. The figure below shows a sample statechart using an operation:
  822. !images/operationExample.png(Specifying an operation callback in the model)!
  823. Let's have a look at the generated code:
  824. bc(prettyprint)..
  825. import java.util.List;
  826. import org.yakindu.scr.IStatemachine;
  827. public interface IDefaultSMStatemachine extends IStatemachine {
  828. public interface SCISample {
  829. public void raiseEvA(boolean value);
  830. public boolean isRaisedEvB();
  831. public long getEvBValue();
  832. public boolean getA();
  833. public void setA(boolean value);
  834. public List<SCISampleListener> getListeners();
  835. public void setSCISampleOperationCallback(SCISampleOperationCallback operationCallback);
  836. }
  837. public interface SCISampleListener {
  838. public void onEvBRaised(long value);
  839. }
  840. public interface SCISampleOperationCallback {
  841. public long myOperation(long p1, boolean p2);
  842. }
  843. public SCISample getSCISample();
  844. }
  845. p. An additional interface @SCISampleOperationCallback@ specifying the method @public long myOperation(long p1, boolean p2)@ has been generated. The client code has to
  846. * provide an implementation of this interface and
  847. * pass an instance of it to the state machine via the @setSCISampleOperationCallback(SCISampleOperationCallback operationCallback)@ method.
  848. Here's some sample code that passes an implementation of the operation to a state machine, and then executes the latter:
  849. bc(prettyprint)..
  850. public static void main(String[] args) {
  851. DefaultSMStatemachine statemachine = new DefaultSMStatemachine();
  852. SCISampleOperationCallback callback = new SCISampleOperationCallback() {
  853. @Override
  854. public long myOperation(long p1, boolean p2) {
  855. // Your operation code should be placed here;
  856. return 0;
  857. }
  858. };
  859. statemachine.getSCISample().setSCISampleOperationCallback(callback);
  860. statemachine.init();
  861. statemachine.enter();
  862. statemachine.runCycle();
  863. }
  864. h4(#JavaIntegratingGeneratedCode). Integrating generated code
  865. To get a clue how to integrate a generated Java state machine with your project have a look at the @CrossingDemoCycleBased@ class and its abstract superclass @CrossingDemoBase@. The @main()@ method is in @CrossingDemoCycleBased@:
  866. bc(prettyprint)..
  867. public static void main(String[] args) {
  868. new CrossingDemoCycleBased().runTrafficLight();
  869. }
  870. p. A new instance of the class is created and the method @runTrafficLight()@ is called. This method can be found in the superclass:
  871. bc(prettyprint)..
  872. public void runTrafficLight() {
  873. setUpAndRunStatemachine();
  874. createUIContent();
  875. shell.open();
  876. while (!shell.isDisposed()) {
  877. // update traffic lights
  878. readStatemachineOutput();
  879. crossing.repaint();
  880. if (!display.readAndDispatch()) {
  881. display.sleep();
  882. }
  883. }
  884. tearDownStatemachine();
  885. }
  886. p. This method sets up the state machine and creates the GUI content. In a while loop it reads the content of the state machine and repaints the GUI. If the user exits the GUI shell, the loop terminates and the state machine is torn down. The really interesting methods are @setUpAndRunStatemachine()@, @readStatemachineOutput@ and @tearDownStatemachine()@:
  887. bc(prettyprint)..
  888. protected void setUpAndRunStatemachine() {
  889. statemachine = new TrafficLightWaitingStatemachine();
  890. statemachine.setTimerService(new TimerService());
  891. statemachine.init();
  892. statemachine.enter();
  893. RuntimeService.getInstance().registerStatemachine(statemachine, 100);
  894. }
  895. p. First a new instance of the generated state machine is created. Since the traffic light statechart uses timing clauses, it is provided with a timer service, here with the default implementation of the @ITimerService@ interface. In the next steps the state machine is initialized and entered. After the @enter()@ method has been executed, the machine is in a defined state.
  896. Finally the state machine is passed to the runtime service. This service executes the @runCycle()@ method of the state machine every 100 ms, that is the state machine executes a run-to-completion step every 100 ms.
  897. bc(prettyprint)..
  898. protected void readStatemachineOutput() {
  899. trafficLightFigure.setRed(statemachine.getSCITrafficLight()
  900. .getRed());
  901. trafficLightFigure.setYellow(statemachine.getSCITrafficLight()
  902. .getYellow());
  903. trafficLightFigure.setGreen(statemachine.getSCITrafficLight()
  904. .getGreen());
  905. pedestrianLightFigure.setWhite(statemachine.getSCIPedestrian()
  906. .getRequest());
  907. pedestrianLightFigure.setRed(statemachine.getSCIPedestrian()
  908. .getRed());
  909. pedestrianLightFigure.setGreen(statemachine.getSCIPedestrian()
  910. .getGreen());
  911. }
  912. p. The generated code contains getters and setters for each variable and event. So it's easy to read values from or write values to a state machine, raise events, or ask the state machine whether outgoing events have been raised during the last run-to-completion step. Within the @readStatemachineOutput()@ method, these methods are used to get the lights values from the state machine and set them to the UI elements. The methods @pedestrianRequestButtonClicked()@ and @onOffButtonClicked()@ raise some events.
  913. Hint: When outgoing events are raised within the state machine, they remain active until the next run-to-completion step is started.
  914. bc(prettyprint)..
  915. @Override
  916. protected void tearDownStatemachine() {
  917. // End TimerHandler and RuntimeService.
  918. statemachine.getTimerService().cancel();
  919. RuntimeService.getInstance().cancelTimer();
  920. }
  921. p. If the UI thread has been terminated by the user, the state machine will be shut down. It is necessary to explicitly end the timer service. Finally the runtime service is cancelled.
  922. h3(#SpecC). Specifications of C code
  923. You can checkout the C sample project _"org.yakindu.sct.examples.c.trafficlight":https://github.com/Yakindu/statecharts/tree/master/examples/org.yakindu.sct.examples.c.trafficlight_ from the "YAKINDU Statechart Tools GitHub repository":https://github.com/Yakindu/statecharts. 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.
  924. To execute the C example, run the file _org_yakindu_sct_examples_c_trafficlight_ as _Local C/C++ application_ from the Eclipse _Run As_ context menu.
  925. h4(#CGeneratedCode). Generated code files
  926. You will find the generated code in the _src-gen_ folder of the traffic light example.
  927. The C code generator generates three header files. The first one is _sc_types.h_:
  928. bc(prettyprint)..
  929. #ifndef SC_TYPES_H_
  930. #define SC_TYPES_H_
  931. #ifdef __cplusplus
  932. extern "C" {
  933. #endif
  934. #include <stdint.h>
  935. #include <stdbool.h>
  936. #define sc_string char*
  937. typedef bool sc_boolean;
  938. typedef int_fast16_t sc_short;
  939. typedef uint_fast16_t sc_ushort;
  940. typedef int32_t sc_integer;
  941. typedef uint32_t sc_uinteger;
  942. typedef double sc_real;
  943. typedef void* sc_eventid;
  944. #ifdef __cplusplus
  945. }
  946. #endif
  947. #ifndef null
  948. #ifdef __cplusplus
  949. #define null 0
  950. #else
  951. #define null ((void *)0)
  952. #endif
  953. #endif
  954. #define bool_true true
  955. #define bool_false false
  956. #endif /* SC_TYPES_H_ */
  957. p. The header file contains some basic definitions for C++ compiler compatibility and typedefs to map the YAKINDU statechart types to C types. The next header file is named after the statechart. In case of the traffic light example it is called _TrafficLightWaiting.h_:
  958. bc(prettyprint)..
  959. #ifndef TRAFFICLIGHTWAITING_H_
  960. #define TRAFFICLIGHTWAITING_H_
  961. #include "sc_types.h"
  962. #ifdef __cplusplus
  963. extern "C" {
  964. #endif
  965. /*! \file Header of the state machine 'TrafficLightWaiting'.
  966. */
  967. /*! Enumeration of all states */
  968. typedef enum {
  969. TrafficLightWaiting_main_region_on,
  970. TrafficLightWaiting_main_region_on_r1_StreetGreen,
  971. TrafficLightWaiting_main_region_on_r1_PedWaiting,
  972. TrafficLightWaiting_main_region_on_r1_PedWaiting_r1_waitOn,
  973. TrafficLightWaiting_main_region_on_r1_PedWaiting_r1_waitOff,
  974. TrafficLightWaiting_main_region_on_r1_StreetAttention,
  975. TrafficLightWaiting_main_region_on_r1_StreetRed,
  976. TrafficLightWaiting_main_region_on_r1_PedestrianGreen,
  977. TrafficLightWaiting_main_region_on_r1_PedestrianRed,
  978. TrafficLightWaiting_main_region_on_r1_StreetPrepare,
  979. TrafficLightWaiting_main_region_off,
  980. TrafficLightWaiting_main_region_off_r1_YellowOn,
  981. TrafficLightWaiting_main_region_off_r1_YellowOff,
  982. TrafficLightWaiting_last_state
  983. } TrafficLightWaitingStates;
  984. /*! Type definition of the data structure for the TrafficLightWaitingIfaceTrafficLight interface scope. */
  985. typedef struct {
  986. sc_boolean red;
  987. sc_boolean yellow;
  988. sc_boolean green;
  989. } TrafficLightWaitingIfaceTrafficLight;
  990. /*! Type definition of the data structure for the TrafficLightWaitingIfacePedestrian interface scope. */
  991. typedef struct {
  992. sc_boolean request;
  993. sc_boolean red;
  994. sc_boolean green;
  995. } TrafficLightWaitingIfacePedestrian;
  996. /*! Type definition of the data structure for the TrafficLightWaitingIface interface scope. */
  997. typedef struct {
  998. sc_boolean pedestrianRequest_raised;
  999. sc_boolean onOff_raised;
  1000. } TrafficLightWaitingIface;
  1001. /*! Type definition of the data structure for the TrafficLightWaitingTimeEvents interface scope. */
  1002. typedef struct {
  1003. sc_boolean trafficLightWaiting_main_region_on_r1_PedWaiting_tev0_raised;
  1004. sc_boolean trafficLightWaiting_main_region_on_r1_PedWaiting_r1_waitOn_tev0_raised;
  1005. sc_boolean trafficLightWaiting_main_region_on_r1_PedWaiting_r1_waitOff_tev0_raised;
  1006. sc_boolean trafficLightWaiting_main_region_on_r1_StreetAttention_tev0_raised;
  1007. sc_boolean trafficLightWaiting_main_region_on_r1_StreetRed_tev0_raised;
  1008. sc_boolean trafficLightWaiting_main_region_on_r1_PedestrianGreen_tev0_raised;
  1009. sc_boolean trafficLightWaiting_main_region_on_r1_PedestrianRed_tev0_raised;
  1010. sc_boolean trafficLightWaiting_main_region_on_r1_StreetPrepare_tev0_raised;
  1011. sc_boolean trafficLightWaiting_main_region_off_r1_YellowOn_tev0_raised;
  1012. sc_boolean trafficLightWaiting_main_region_off_r1_YellowOff_tev0_raised;
  1013. } TrafficLightWaitingTimeEvents;
  1014. /*! Define dimension of the state configuration vector for orthogonal states. */
  1015. #define TRAFFICLIGHTWAITING_MAX_ORTHOGONAL_STATES 1
  1016. /*!
  1017. * Type definition of the data structure for the TrafficLightWaiting state machine.
  1018. * This data structure has to be allocated by the client code.
  1019. */
  1020. typedef struct {
  1021. TrafficLightWaitingStates stateConfVector[TRAFFICLIGHTWAITING_MAX_ORTHOGONAL_STATES];
  1022. sc_ushort stateConfVectorPosition;
  1023. TrafficLightWaitingIfaceTrafficLight ifaceTrafficLight;
  1024. TrafficLightWaitingIfacePedestrian ifacePedestrian;
  1025. TrafficLightWaitingIface iface;
  1026. TrafficLightWaitingTimeEvents timeEvents;
  1027. } TrafficLightWaiting;
  1028. /*! Initializes the TrafficLightWaiting state machine data structures. Must be called before first usage.*/
  1029. extern void trafficLightWaiting_init(TrafficLightWaiting* handle);
  1030. /*! Activates the state machine */
  1031. extern void trafficLightWaiting_enter(TrafficLightWaiting* handle);
  1032. /*! Deactivates the state machine */
  1033. extern void trafficLightWaiting_exit(TrafficLightWaiting* handle);
  1034. /*! Performs a 'run to completion' step. */
  1035. extern void trafficLightWaiting_runCycle(TrafficLightWaiting* handle);
  1036. /*! Raises a time event. */
  1037. extern void trafficLightWaiting_raiseTimeEvent(const TrafficLightWaiting* handle, sc_eventid evid);
  1038. /*! Gets the value of the variable 'red' that is defined in the interface scope 'TrafficLight'. */
  1039. extern sc_boolean trafficLightWaitingIfaceTrafficLight_get_red(const TrafficLightWaiting* handle);
  1040. /*! Sets the value of the variable 'red' that is defined in the interface scope 'TrafficLight'. */
  1041. extern void trafficLightWaitingIfaceTrafficLight_set_red(TrafficLightWaiting* handle, sc_boolean value);
  1042. /*! Gets the value of the variable 'yellow' that is defined in the interface scope 'TrafficLight'. */
  1043. extern sc_boolean trafficLightWaitingIfaceTrafficLight_get_yellow(const TrafficLightWaiting* handle);
  1044. /*! Sets the value of the variable 'yellow' that is defined in the interface scope 'TrafficLight'. */
  1045. extern void trafficLightWaitingIfaceTrafficLight_set_yellow(TrafficLightWaiting* handle, sc_boolean value);
  1046. /*! Gets the value of the variable 'green' that is defined in the interface scope 'TrafficLight'. */
  1047. extern sc_boolean trafficLightWaitingIfaceTrafficLight_get_green(const TrafficLightWaiting* handle);
  1048. /*! Sets the value of the variable 'green' that is defined in the interface scope 'TrafficLight'. */
  1049. extern void trafficLightWaitingIfaceTrafficLight_set_green(TrafficLightWaiting* handle, sc_boolean value);
  1050. /*! Gets the value of the variable 'request' that is defined in the interface scope 'Pedestrian'. */
  1051. extern sc_boolean trafficLightWaitingIfacePedestrian_get_request(const TrafficLightWaiting* handle);
  1052. /*! Sets the value of the variable 'request' that is defined in the interface scope 'Pedestrian'. */
  1053. extern void trafficLightWaitingIfacePedestrian_set_request(TrafficLightWaiting* handle, sc_boolean value);
  1054. /*! Gets the value of the variable 'red' that is defined in the interface scope 'Pedestrian'. */
  1055. extern sc_boolean trafficLightWaitingIfacePedestrian_get_red(const TrafficLightWaiting* handle);
  1056. /*! Sets the value of the variable 'red' that is defined in the interface scope 'Pedestrian'. */
  1057. extern void trafficLightWaitingIfacePedestrian_set_red(TrafficLightWaiting* handle, sc_boolean value);
  1058. /*! Gets the value of the variable 'green' that is defined in the interface scope 'Pedestrian'. */
  1059. extern sc_boolean trafficLightWaitingIfacePedestrian_get_green(const TrafficLightWaiting* handle);
  1060. /*! Sets the value of the variable 'green' that is defined in the interface scope 'Pedestrian'. */
  1061. extern void trafficLightWaitingIfacePedestrian_set_green(TrafficLightWaiting* handle, sc_boolean value);
  1062. /*! Raises the in event 'pedestrianRequest' that is defined in the default interface scope. */
  1063. extern void trafficLightWaitingIface_raise_pedestrianRequest(TrafficLightWaiting* handle);
  1064. /*! Raises the in event 'onOff' that is defined in the default interface scope. */
  1065. extern void trafficLightWaitingIface_raise_onOff(TrafficLightWaiting* handle);
  1066. /*!
  1067. * Checks if the statemachine is active (until 2.4.1 this method was used for states).
  1068. * A statemachine is active if it was entered. It is inactive if it has not been entered at all or if it was exited.
  1069. */
  1070. extern sc_boolean trafficLightWaiting_isActive(const TrafficLightWaiting* handle);
  1071. /*!
  1072. * Checks if all active states are final.
  1073. * If there are no active states then the statemachine is considered as inactive and this method returns false.
  1074. */
  1075. extern sc_boolean trafficLightWaiting_isFinal(const TrafficLightWaiting* handle);
  1076. /*! Checks if the specified state is active (until 2.4.1 the used method for states was calles isActive()). */
  1077. extern sc_boolean trafficLightWaiting_isStateActive(const TrafficLightWaiting* handle, TrafficLightWaitingStates state);
  1078. #ifdef __cplusplus
  1079. }
  1080. #endif
  1081. #endif /* TRAFFICLIGHTWAITING_H_ */
  1082. p. Within this header file an @enum@ containing the state names is defined as well as data structures for each of the statechart's interfaces. Additionally a structure for the statechart's time events is defined. The interfaces' and time events' data structures are nested into the parent structure @TrafficLightWaiting@. The client has to allocate this structure. It is a common parameter of most methods the statechart defines. Below this structure is called the _statechart data structure_.
  1083. h5. Fundamental statechart methods
  1084. The generated code contains fundamental methods to initialize, enter, and exit a state machine, as well as a method to start a run-to-completion step.
  1085. In the header file the method names are made up of the statechart name followed by the name of the respective functionality. For example, the methods of the traffic light example are generated as follows:
  1086. bc(prettyprint)..
  1087. extern void trafficLightWaiting_init(TrafficLightWaiting* handle);
  1088. extern void trafficLightWaiting_enter(TrafficLightWaiting* handle);
  1089. extern void trafficLightWaiting_exit(TrafficLightWaiting* handle);
  1090. extern void trafficLightWaiting_runCycle(TrafficLightWaiting* handle);
  1091. p.
  1092. * The @init()@ method is used to initialize the statechart data structure right after its instantiation. Variables are initialized to their respective default values. If the statechart defines initialized variables, these initializations are also done in the @init()@ method.
  1093. * The @enter()@ method must be called to enter the state machine. It brings the state machine to a well-defined state.
  1094. * The @exit()@ method 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.
  1095. * The @runCycle()@ method 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:
  1096. # Clear list of outgoing events.
  1097. # Check whether events have occurred which are leading to a state change.
  1098. # If a state change has to be done:
  1099. ## Execute exit actions of the present state.
  1100. ## Save history state, if necessary.
  1101. ## Make the new state active. ==<!-- FIXME: We should also make the old state inactive, shouldn't we? -->==
  1102. ## Execute entry actions of the new state.
  1103. # Clear list of incoming events.
  1104. h5. Accessing variables and events
  1105. The getters and setters for each variable and event are also contained in the header file. The method names are matching the following pattern: _statechart_name_<code>Iface</code>_interface_name_@_@[ <code>set</code> | <code>get</code> | <code>raise</code> ]@_@[ _variable_name_ | _event_name_ ]. For example, the getter of the _red_ variable of the _pedestrian_ interface is named @trafficLightWaitingIfacePedestrian_get_red(TrafficLightWaiting* handle)@.
  1106. h4. Time-controlled state machines
  1107. If a statechart uses timing functionality or external operations, an additional header file is generated. Its name matches the pattern _statechart_name_@Required.h@. This header file defines method hooks the client code has to implement externally.
  1108. The traffic light example uses timing funtionality, namely _after_ clauses. To support time-controlled behavior, such an additional header file is generated.
  1109. bc(prettyprint)..
  1110. #ifndef TRAFFICLIGHTWAITINGREQUIRED_H_
  1111. #define TRAFFICLIGHTWAITINGREQUIRED_H_
  1112. #include "sc_types.h"
  1113. #include "TrafficLightWaiting.h"
  1114. #ifdef __cplusplus
  1115. extern "C" {
  1116. #endif
  1117. /*! \file This header defines prototypes for all functions that are required by the state machine implementation.
  1118. This is a state machine uses time events which require access to a timing service. Thus the function prototypes:
  1119. - trafficLightWaiting_setTimer and
  1120. - trafficLightWaiting_unsetTimer
  1121. are defined.
  1122. These functions will be called during a 'run to completion step' (runCycle) of the statechart.
  1123. There are some constraints that have to be considered for the implementation of these functions:
  1124. - never call the statechart API functions from within these functions.
  1125. - make sure that the execution time is as short as possible.
  1126. */
  1127. /*!
  1128. * This is a timed state machine that requires timer services
  1129. */
  1130. /*! This function has to set up timers for the time events that are required by the state machine. */
  1131. /*!
  1132. This function will be called for each time event that is relevant for a state when a state will be entered.
  1133. \param evid An unique identifier of the event.
  1134. \time_ms The time in milli seconds
  1135. \periodic Indicates the the time event must be raised periodically until the timer is unset
  1136. */
  1137. extern void trafficLightWaiting_setTimer(TrafficLightWaiting* handle, const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic);
  1138. /*! This function has to unset timers for the time events that are required by the state machine. */
  1139. /*!
  1140. This function will be called for each time event taht is relevant for a state when a state will be left.
  1141. \param evid An unique identifier of the event.
  1142. */
  1143. extern void trafficLightWaiting_unsetTimer(TrafficLightWaiting* handle, const sc_eventid evid);
  1144. #ifdef __cplusplus
  1145. }
  1146. #endif
  1147. #endif /* TRAFFICLIGHTWAITINGREQUIRED_H_ */
  1148. 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 the client code must provide a method to set a timer and another method to unset it. These methods have to be implemented externally and linked to the generated code.
  1149. p. The following methods are dealing with timing functionality:
  1150. h5. Method setTimer
  1151. p. A state machine calls the @setTimer()@ method – short for the method's full name like e.&nbsp;g. @void trafficLightWaiting_setTimer(TrafficLightWaiting* handle, const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic)@ – to tell the timer service that it has to start a timer for the given time event identifier and raise it after the period of time specified by the _time_ms_ parameter has expired. It is important to only start a timer thread or a hardware timer interrupt within the @setTimer()@ method and avoid any time-consuming operations like extensive computations, sleeping or waiting. Never call the statechart API functions from within these functions! Otherwise the state machine execution might hang within the timer service or might not show the expected runtime behavior.
  1152. In order to have the timer service raise the time event periodically, the parameter _periodic_ must be _true_.
  1153. h5. Method unsetTimer
  1154. p. The state machine calls the method @trafficLightWaiting_setTimer(TrafficLightWaiting* handle, const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic)@ to notify the timer service to unset the timer for the given event ID.
  1155. h5. Method raiseTimeEvent
  1156. p. In order to notify the state machine about the occurence of a time event after a period of time has expired, the @raiseTimeEvent()@ method – defined in the header file of the state machine – is called on the state machine. In the case of the traffic light example it is named @trafficLightWaiting_raiseTimeEvent(const TrafficLightWaiting* handle, sc_eventid evid)@ (in file _TrafficLightWaiting.h_).
  1157. The time event is recognized by the state machine and will be processed during the next run cycle.
  1158. 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()@ method 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()@ method with a frequency of once per 1000 ms only, the event will quite likely not be processed at the correct points in time.
  1159. h4(#COperationCallbacks). Operation callbacks
  1160. 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 order to make a statechart executable. The figure below shows a sample statechart using an operation:
  1161. !images/operationExample.png(Specifying an operation callback in the model)!
  1162. Let's have a look at the generated code:
  1163. bc(prettyprint)..
  1164. #ifndef DEFAULTSMREQUIRED_H_
  1165. #define DEFAULTSMREQUIRED_H_
  1166. #include "sc_types.h"
  1167. #include "DefaultSM.h"
  1168. #ifdef __cplusplus
  1169. extern "C" {
  1170. #endif
  1171. /*! \file This header defines prototypes for all functions that are required by the state machine implementation.
  1172. This state machine makes use of operations declared in the state machines interface or internal scopes. Thus the function prototypes:
  1173. - defaultSMIfaceSample_myOperation
  1174. are defined.
  1175. These functions will be called during a 'run to completion step' (runCycle) of the statechart.
  1176. There are some constraints that have to be considered for the implementation of these functions:
  1177. - never call the statechart API functions from within these functions.
  1178. - make sure that the execution time is as short as possible.
  1179. */
  1180. extern sc_integer defaultSMIfaceSample_myOperation(DefaultSM* handle, const sc_integer p1, const sc_boolean p2);
  1181. #ifdef __cplusplus
  1182. }
  1183. #endif
  1184. #endif /* DEFAULTSMREQUIRED_H_ */
  1185. p. An additional method @sc_integer defaultSMIfaceSample_myOperation(DefaultSM* handle, const sc_integer p1, const sc_boolean p2)@ has been generated. This method has to be implemented and linked with the generated code, so that the state machine can use it.
  1186. h4(#CIntegratingGeneratedCode). Integrating generated code
  1187. To get a clue how to integrate a generated C state machines with your project have a look at the @main.cpp@ file and its @main()@ method:
  1188. bc(prettyprint)..
  1189. #include "org_yakindu_sct_examples_c_trafficlight.h"
  1190. #include <QtGui>
  1191. #include <QApplication>
  1192. #include "src-gen/sc_types.h"
  1193. #include "src-gen/TrafficLightWaiting.h"
  1194. #include "statemachine/TrafficLightTimer.h"
  1195. #include "statemachine/TrafficLightRunner.h"
  1196. TrafficLightTimer *timer;
  1197. int main(int argc, char *argv[]) {
  1198. TrafficLightWaiting handle;
  1199. trafficLightWaiting_init(&handle);
  1200. timer = new TrafficLightTimer(&handle);
  1201. trafficLightWaiting_enter(&handle);
  1202. QApplication a(argc, argv);
  1203. TrafficLightRunner *runner = new TrafficLightRunner(&handle, 100);
  1204. org_yakindu_sct_examples_c_trafficlight w(0, runner);
  1205. w.show();
  1206. int ret = a.exec();
  1207. return ret;
  1208. }
  1209. void trafficLightWaiting_setTimer(const sc_eventid evid,
  1210. const sc_integer time_ms, const sc_boolean periodic) {
  1211. timer->setTimer(evid, time_ms, periodic);
  1212. }
  1213. void trafficLightWaiting_unsetTimer(const sc_eventid evid) {
  1214. timer->unsetTimer(evid);
  1215. }
  1216. p. First an instance of the statechart data structure is created and initialized by the @trafficLightWaiting_init(&handle)@ method. The next step instantiates the timer. The class @TrafficLightTimer@ represents an implementation of a timer service and uses the timer fuctionality of the Qt framework. The @TrafficLightRunner@ is a runtime service which executes a run-to-completion step of the state machine every 100 ms. The runner class and the GUI are wired in the class @org_yakindu_sct_examples_c_trafficlight@:
  1217. bc(prettyprint)..
  1218. #include "org_yakindu_sct_examples_c_trafficlight.h"
  1219. org_yakindu_sct_examples_c_trafficlight::org_yakindu_sct_examples_c_trafficlight(
  1220. QWidget *parent, TrafficLightRunner *runner) :
  1221. QMainWindow(parent) {
  1222. ui.setupUi(this);
  1223. crossing = new CrossingWidget(this);
  1224. trafficLight = new TrafficLightWidget(crossing);
  1225. trafficLight->setGeometry(275, 75, 30, 90);
  1226. pedestrianLight = new PedestrianLightWidget(crossing);
  1227. pedestrianLight->setGeometry(50, 10, 70, 20);
  1228. connect(runner, SIGNAL(cycleDone(TrafficLightWaiting*)), this, SLOT(update(TrafficLightWaiting*)));
  1229. pedestrianReq = new QPushButton("pedestrian request", this);
  1230. pedestrianReq->setGeometry(1, 365, 150, 30);
  1231. connect(pedestrianReq, SIGNAL(released()), runner, SLOT(raisePedestrianRequest()));
  1232. off = new QPushButton("off / on", this);
  1233. off->setGeometry(249, 365, 150, 30);
  1234. connect(off, SIGNAL(released()), runner, SLOT(raiseOnOff()));
  1235. }
  1236. void org_yakindu_sct_examples_c_trafficlight::update(
  1237. TrafficLightWaiting *handle) {
  1238. trafficLight->setSignals(handle->ifaceTrafficLight.red,
  1239. handle->ifaceTrafficLight.yellow, handle->ifaceTrafficLight.green);
  1240. pedestrianLight->setSignals(handle->ifacePedestrian.request,
  1241. handle->ifacePedestrian.red, handle->ifacePedestrian.green);
  1242. QMainWindow::update();
  1243. }
  1244. org_yakindu_sct_examples_c_trafficlight::~org_yakindu_sct_examples_c_trafficlight() {
  1245. }
  1246. h3(#CppSpec). Specifications of C++ code
  1247. You can checkout the C++ sample project _"QtTrafficLightCpp":http://svn.codespot.com/a/eclipselabs.org/yakindu/SCT2/trunk/examples_ from the "YAKINDU Google Code repository":http://svn.codespot.com/a/eclipselabs.org/yakindu/SCT2/trunk. 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.
  1248. ==<!-- FIXME: C: To execute the C example, run the file _org_yakindu_sct_examples_c_trafficlight_ as "Local C/C++ application" from the Eclipse _Run As_ context menu. -->==
  1249. h4(#CppGeneratedCode). Generated code files
  1250. You will find the generated code in the _src-gen_ folder of the traffic light example.
  1251. 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.
  1252. h4. Statemachine class
  1253. 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 will be generated as the source code file _DefaultSM.cpp_.
  1254. h4. Abstract class StatemachineInterface
  1255. Each generated state machine implements the interface @StatemachineInterface@:
  1256. bc(prettyprint)..
  1257. #ifndef STATEMACHINEINTERFACE_H_
  1258. #define STATEMACHINEINTERFACE_H_
  1259. /*
  1260. * Basic interface for statemachines.
  1261. */
  1262. class StatemachineInterface {
  1263. public:
  1264. virtual ~StatemachineInterface() = 0;
  1265. /*
  1266. * Initializes the statemachine. Use to init internal variables etc.
  1267. */
  1268. virtual void init() = 0;
  1269. /*
  1270. * Enters the statemachine. Sets the statemachine in a defined state.
  1271. */
  1272. virtual void enter() = 0;
  1273. /*
  1274. * Exits the statemachine. Leaves the statemachine with a defined state.
  1275. */
  1276. virtual void exit() = 0;
  1277. /*
  1278. * Start a run-to-completion cycle.
  1279. */
  1280. virtual void runCycle() = 0;
  1281. /*
  1282. * Checks if the statemachine is active.
  1283. * A statemachine is active if it was entered. It is inactive if it has not been entered at all or if it was exited.
  1284. */
  1285. virtual sc_boolean isActive() = 0;
  1286. /*
  1287. * Checks if all active states are final.
  1288. * If there are no active states then the statemachine is considered as inactive and this method returns false.
  1289. */
  1290. virtual sc_boolean isFinal() = 0;
  1291. };
  1292. inline StatemachineInterface::~StatemachineInterface() {}
  1293. #endif /* STATEMACHINEINTERFACE_H_ */
  1294. h5. Fundamental statechart methods
  1295. The generated code contains fundamental methods to initialize, enter, and exit a state machine, as well as a method to start a run-to-completion step.
  1296. The @StatemachineInterface@ interface specifies the four functions @init()@, @enter()@, @exit()@ and @runCycle()@.
  1297. * 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 initialized variables, these initializations are also done in the @init()@ function.
  1298. * The @enter()@ function must be called to enter the state machine. It brings the state machine to a well-defined state.
  1299. * 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.
  1300. * 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:
  1301. # Clear list of outgoing events.
  1302. # Check whether events have occurred which are leading to a state change.
  1303. # If a state change has to be done:
  1304. ## Execute exit actions of the present state.
  1305. ## Save history state, if necessary.
  1306. ## Make the new state active. ==<!-- FIXME: We should also make the old state inactive, shouldn't we? -->==
  1307. ## Execute entry actions of the new state.
  1308. # Clear list of incoming events.
  1309. h4. Time-controlled state machines
  1310. If a statechart uses timing functionality, additional classes are generated.
  1311. The traffic light example uses timing funtionality, namely _after_ clauses. To support time-controlled behavior, the abstract classes @TimedStatemachineInterface@ and @TimerInterface@ are generated.
  1312. The @TimedStatemachineInterface@ interface extends the generated state machine by a @TimerInterface@ data member. The client code must provide an implementation of that interface.
  1313. @TimedStatemachineInterface@ also specifies the callback function @raiseTimeEvent(sc_eventid event)@, enabling the timer service to raise time events.
  1314. bc(prettyprint)..
  1315. #ifndef TIMEDSTATEMACHINEINTERFACE_H_
  1316. #define TIMEDSTATEMACHINEINTERFACE_H_
  1317. #include "sc_types.h"
  1318. #include "TimerInterface.h"
  1319. /*
  1320. * Interface for state machines which use timed event triggers.
  1321. */
  1322. class TimedStatemachineInterface {
  1323. public:
  1324. virtual ~TimedStatemachineInterface() = 0;
  1325. /*
  1326. * Set the ITimerService for the state machine. It must be set
  1327. * externally on a timed state machine before a run cycle can be correct
  1328. * executed.
  1329. */
  1330. virtual void setTimer(TimerInterface* timer) = 0;
  1331. /*
  1332. * Returns the currently used timer service.
  1333. */
  1334. virtual TimerInterface* getTimer() = 0;
  1335. /*
  1336. * Callback method if a time event occurred.
  1337. */
  1338. virtual void raiseTimeEvent(sc_eventid event) = 0;
  1339. };
  1340. inline TimedStatemachineInterface::~TimedStatemachineInterface() {}
  1341. #endif /* TIMEDSTATEMACHINEINTERFACE_H_ */
  1342. 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.
  1343. Let's have a look at the @TimerInterface@ interface:
  1344. bc(prettyprint)..
  1345. #ifndef TIMERINTERFACE_H_
  1346. #define TIMERINTERFACE_H_
  1347. #include "sc_types.h"
  1348. //forward declaration of TimedStatemachineInterface to avoid cyclic dependency
  1349. class TimedStatemachineInterface;
  1350. /*
  1351. * Basic interface for statemachines.
  1352. */
  1353. class TimerInterface {
  1354. public:
  1355. virtual ~TimerInterface() = 0;
  1356. /*
  1357. * Starts the timing for a time event.
  1358. */
  1359. virtual void setTimer(TimedStatemachineInterface* statemachine, sc_eventid event, sc_integer time, sc_boolean isPeriodic) = 0;
  1360. /*
  1361. * Unsets the given time event.
  1362. */
  1363. virtual void unsetTimer(TimedStatemachineInterface* statemachine, sc_eventid event) = 0;
  1364. /*
  1365. * Cancel timer service. Use this to end possible timing threads and free
  1366. * memory resources.
  1367. */
  1368. virtual void cancel() = 0;
  1369. };
  1370. inline TimerInterface::~TimerInterface() {}
  1371. #endif /* TIMERINTERFACE_H_ */
  1372. p. The @TimerInterface@ interface defines the following functions dealing with timing functionality:
  1373. h5. Function setTimer
  1374. p. 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.
  1375. In order to have the timer service raise the time event periodically, the parameter _isPeriodic_ must be _true_.
  1376. h5. Function unsetTimer
  1377. p. 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.
  1378. h5. Function raiseTimeEvent
  1379. p. 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.
  1380. The time event is recognized by the state machine and will be processed during the next run cycle.
  1381. 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.
  1382. h4(#CppInterVar). Accessing interfaces, variables and events
  1383. 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.
  1384. Let's have a look at the following sample statechart interface declaration of a statechart named _DefaultSM_:
  1385. bc(prettyprint)..
  1386. interface Sample:
  1387. var a:boolean
  1388. in event evA:boolean
  1389. out event evB:integer
  1390. p. The generated interface code is shown below. Since the statechart's name is _DefaultSM_ the state machine class' name is also _DefaultSM_, to be found in the _DefaultSM.h_ file. The following is a snippet from that file.
  1391. bc(prettyprint)..
  1392. //! Inner class for Sample interface scope.
  1393. class SCI_Sample {
  1394. public:
  1395. /*! Gets the value of the variable 'a' that is defined in the interface scope 'Sample'. */
  1396. sc_boolean get_a();
  1397. /*! Sets the value of the variable 'a' that is defined in the interface scope 'Sample'. */
  1398. void set_a(sc_boolean value);
  1399. /*! Raises the in event 'evA' that is defined in the interface scope 'Sample'. */
  1400. void raise_evA(sc_boolean value);
  1401. /*! Checks if the out event 'evB' that is defined in the interface scope 'Sample' has been raised. */
  1402. sc_boolean isRaised_evB();
  1403. /*! Gets the value of the out event 'evB' that is defined in the interface scope 'Sample'. */
  1404. sc_integer get_evB_value();
  1405. private:
  1406. friend class DefaultSM;
  1407. sc_boolean a;
  1408. sc_boolean evA_raised;
  1409. sc_boolean evA_value;
  1410. sc_boolean evB_raised;
  1411. sc_integer evB_value;
  1412. };
  1413. 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_@.
  1414. A special case is the unnamed statechart interface: It is generated as the C++ subclass @SCInterface@.
  1415. 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.
  1416. 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.
  1417. For variables, the code generator creates getter and setter functions, here @sc_boolean get_a()@ and @void set_a(sc_boolean value)@.
  1418. 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()@.
  1419. 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:
  1420. bc(prettyprint)..
  1421. void DefaultSM::SCI_Sample::raise_evA(sc_boolean value) {
  1422. evA_value = value;
  1423. evA_raised = true;
  1424. }
  1425. sc_boolean DefaultSM::SCI_Sample::isRaised_evB() {
  1426. return evB_raised;
  1427. }
  1428. sc_integer DefaultSM::SCI_Sample::get_evB_value() {
  1429. return evB_value;
  1430. }
  1431. sc_boolean DefaultSM::SCI_Sample::get_a() {
  1432. return a;
  1433. }
  1434. void DefaultSM::SCI_Sample::set_a(sc_boolean value) {
  1435. a = value;
  1436. }
  1437. 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.
  1438. ==<!-- h4(#CppInterfaceObservers). Interface observers -->==
  1439. ==<!-- In Java we have such a chapter. What about a C++ equivalent? -->==
  1440. h4(#CppOperationCallbacks). Operation callbacks
  1441. 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 order to make a statechart executable. The figure below shows a sample statechart using an operation:
  1442. !images/operationExample.png(Specifying an operation callback in the model)!
  1443. Let's have a look at the additionally generated code for operation support in the _DefaultSM.h_ header file:
  1444. bc(prettyprint)..
  1445. //! Inner class for Sample interface scope operation callbacks.
  1446. class SCI_Sample_OCB {
  1447. public:
  1448. virtual ~SCI_Sample_OCB() = 0;
  1449. virtual sc_integer myOperation(sc_integer p1, sc_boolean p2) = 0;
  1450. };
  1451. /*! Set the working instance of the operation callback interface 'SCI_Sample_OCB'. */
  1452. void setSCI_Sample_OCB(SCI_Sample_OCB* operationCallback);
  1453. 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.
  1454. bc(prettyprint)..
  1455. #include "DefaultSM.h"
  1456. sc_integer DefaultSM::SCI_Sample_OCB::myOperation(sc_integer p1, sc_boolean p2) {
  1457. // Your operation code should be placed here;
  1458. return 0;
  1459. }
  1460. int main(int argc, char *argv[]) {
  1461. DefaultSM *defaultSM = new DefaultSM();
  1462. SCI_Sample_OCB *sci_Sample_OCB = new SCI_Sample_OCB();
  1463. defaultSM->setSCI_Sample_OCB(sci_Sample_OCB);
  1464. defaultSM->init();
  1465. defaultSM->enter();
  1466. defaultSM->runCycle();
  1467. }
  1468. p.
  1469. ==<!-- h4(#CppIntegratingGeneratedCode). Integrating generated code -->==
  1470. ==<!-- This chapter is available for Java and C, but missing for C++. -->==