openETCS
case study for the European Train Control System developed for the authors dissertation
EVCStateMachine.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010-2012
3  Johannes Feuser <feuser@uni-bremen.de>
4  This file is part of the openETCS library.
5 
6  The openETCS library is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  any later version.
10 
11  The openETCS library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with the openETCS library. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /*!
21  * \author Johannes Feuser <feuser@uni-bremen.de>
22  * \brief EVC State machine class and all further classes needed for the core functionality
23  */
24 
25 #include "EVCStateMachine.h"
26 #include "Transition.h"
27 #include "Language.h"
28 #include "Storage.h"
29 #include "FunctionBlocks.h"
30 
31 
32 
33 
34 namespace oETCS {
35 
36 namespace DF {
37 
38 
39 CEVCStateMachine::CEVCState::CDataFlow::CDataFlow(oETCS::DF::CEVCStateMachine::CEVCState * const pState, const std::string & ApplicationLevel, const ::std::vector< oETCS::DF::CFunctionBlock * >& FunctionBlocks, const ::std::vector< oETCS::DF::CAbstractFlow * >& Flows, oETCS::DF::CDMISubject * const pDMI, oETCS::DF::CEVCStateMachine::CEVCState * const pFaultState) throw()
40 :m_pDMI(pDMI),
41  m_FunctionBlocks(FunctionBlocks),
42  m_Flows(Flows),
43  m_pParent(pState),
44  m_pFaultState(pFaultState)
45 {
46  // Bouml preserved body begin 0005F982
47  // add this data flow object to parent EVC state
48  m_pParent->AddDataFlow(ApplicationLevel, this);
49  // Bouml preserved body end 0005F982
50 
51 } // CEVCStateMachine::CEVCState::CDataFlow::CDataFlow() throw()
52 
53 
54 
55 
57 {
58  // Bouml preserved body begin 0005FA02
59  // delete DMI widget
60  delete m_pDMI;
61  // Bouml preserved body end 0005FA02
62 
63 } // CEVCStateMachine::CEVCState::CDataFlow::~CDataFlow() throw()
64 
65 
66 
67 
68 ::std::vector< oETCS::DF::CFunctionBlock* > CEVCStateMachine::CEVCState::CDataFlow::GetFunctionBlocks() const throw()
69 {
70  // Bouml preserved body begin 00087B02
71  // return vector of function block pointers
72  return (m_FunctionBlocks);
73  // Bouml preserved body end 00087B02
74 
75 } // oETCS::DF::CFunctionBlock CEVCStateMachine::CEVCState::CDataFlow::GetFunctionBlocks() const throw()
76 
77 
78 
79 
81 {
82  // Bouml preserved body begin 00063482
83  unsigned int x;
84  const unsigned int NUMBER_FUNCTION_BLOCKS(m_FunctionBlocks.size());
85  bool bFound(false);
86 
87 
88  // process all function block objects
89  for (x = 0; x < NUMBER_FUNCTION_BLOCKS && !bFound; x++)
90  {
91  // compare current function block address with parameter
92  bFound = (pFunctionBlock == m_FunctionBlocks[x]);
93 
94  // check, if not is identical, if current function block is a control flow
95  if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x]) != 0)
96  {
97  // get result form control flow
98  bFound = dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x])->IsActiveFunctionBlock(pFunctionBlock);
99 
100  } // if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x]) != 0)
101 
102  } // for (x = 0; x < NUMBER_FUNCTION_BLOCKS && !bFound; x++)
103 
104  // return found flag
105  return (bFound);
106  // Bouml preserved body end 00063482
107 
108 } // bool CEVCStateMachine::CEVCState::CDataFlow::IsActiveFunctionBlock() const throw()
109 
110 
111 
112 
114 {
115  // Bouml preserved body begin 000C5682
116  bool bFound(false);
117  decltype (m_Flows.begin()) f;
118  decltype (m_FunctionBlocks.begin()) fb;
119 
120 
121 
122  // check all flows in this data flow for parameter
123  for (f = m_Flows.begin(); f != m_Flows.end() && not bFound; f++)
124  {
125  // check, if current flow is searched flow
126  bFound = (pFlow == *f);
127 
128  } // for (f = m_Flows.begin(); f != m_Flows.end() && not bFound; f++)
129 
130  // check all control flow objects
131  for (fb = m_FunctionBlocks.begin(); fb != m_FunctionBlocks.end() && not bFound; fb++)
132  {
133  // check, if current is a control flow
134  if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(*fb) != nullptr)
135  {
136  // call method recursively on control flow
137  bFound = static_cast< ::oETCS::DF::CControlFlow* >(*fb)->IsActiveFlow(pFlow);
138 
139  } // if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(*fb) != nullptr)
140 
141  } // for (fb = m_FunctionBlocks.begin(); fb != m_FunctionBlocks.end() && not bFound; fb++)
142 
143  // return found flag
144  return (bFound);
145  // Bouml preserved body end 000C5682
146 
147 } // bool CEVCStateMachine::CEVCState::CDataFlow::IsActiveFlow() const throw()
148 
149 
150 
151 
152 void CEVCStateMachine::CEVCState::CDataFlow::Execute() throw(::oETCS::DF::Error::CException)
153 {
154  // Bouml preserved body begin 00066A82
155  unsigned int x;
156  const unsigned int NUMBER_FUNCTION_BLOCKS(m_FunctionBlocks.size());
157 
158 
159  try
160  {
161  // execute all function block elements in their order
162  for (x = 0; x < NUMBER_FUNCTION_BLOCKS; x++)
163  {
164  // check, if this is first execution point (k=0) for this data flow
166  {
167  // check, if current function block object is of type CComBlockIn
168  if (dynamic_cast< ::oETCS::DF::CComBlockIn* >(m_FunctionBlocks[x]) != nullptr)
169  {
170  // clear all old telegrams on object
171  static_cast< ::oETCS::DF::CComBlockIn* >(m_FunctionBlocks[x])->Clear();
172 
173  } // if (dynamic_cast< ::oETCS::DF::CComBlockIn* >(m_FunctionBlocks[x]) != nullptr)
174 
175  } // if (::oETCS::DF::CEnteredTrigger::m_bEnteredState)
176 
177  // execute current function block object
178  m_FunctionBlocks[x]->Calculate();
179 
180  } // for (x = 0; x < NUMBER_FUNCTION_BLOCKS; x++)
181 
182  } // try
183  catch (const ::oETCS::DF::Error::CException& Exception)
184  {
185 
186 #ifdef __DEBUG_OUTPUT__
187  // DEBUG
188  ::std::cerr << std::this_thread::get_id() << " " << "CDataFlow::Execute() ----> exception in function block object " << x << ::std::endl;
189 #endif
190 
191  // check, if fault state is available in this data flow
192  if (m_pFaultState != 0)
193  {
194  // currently no differentiation between exception types (faults / errors)
196 
197  // activate level switch
199 
200  // print error for debugging purpose
201  ::std::cerr << "Error while executing data flow: " << Exception.what() << " in " << __FILE__ << " at line " << __LINE__ << ::std::endl;
202 
203  } // if (m_pFaultState != 0)
204  else
205  {
206  // without fault state simply re-throw exception (disabled for testing purpose)
207  //throw;
208 
209  // print warning and just ignore error (for testing purpose)
210  ::std::cerr << "Error while executing data flow, but now fault state available: " << Exception.what() << " in " << __FILE__ << " at line " << __LINE__ << ::std::endl;
211 
212  } // else
213 
214  } // catch (const ::oETCS::DF::Error::CException& Exception)
215 
216  // Bouml preserved body end 00066A82
217 
218 } // void CEVCStateMachine::CEVCState::CDataFlow::Execute() throw(::oETCS::DF::Error::CException)
219 
220 
221 
222 
224 :m_bStateLevelSwitch(false),
225  m_iLockedThreads(0),
226  m_pParent(pParent),
227  m_Transitions(0),
229 {
230  // Bouml preserved body begin 0005FB02
231  // check, if pointer to parent is valid
232  if (m_pParent != 0)
233  {
234  // add this state to parent state machine
235  m_pParent->AddState(this);
236 
237  } // if (m_pParent != 0)
238  // Bouml preserved body end 0005FB02
239 
240 } // CEVCStateMachine::CEVCState::CEVCState() throw()
241 
242 
243 
244 
246 {
247  // Bouml preserved body begin 0005FB82
248  unsigned int x(0);
249  decltype (m_DataFlows.begin()) y(0);
250 
251 
252 
253  // check, if state is running
254  if (this->IsRunning())
255  {
256  // stop state
257  this->Stop();
258 
259  } // if (this->IsRunning())
260 
261  // delete all transitions
262  for (x = 0; x < m_Transitions.size(); x++)
263  {
264  // delete current transition object
265  delete m_Transitions[x];
266 
267  } // for (x = 0; x < m_Transitions.size(); x++)
268 
269  // delete all data flows by their application level
270  for (y = m_DataFlows.begin(); y != m_DataFlows.end(); y++)
271  {
272  // delete all data flow objects in current application level
273  for (x = 0; x < y->second.size(); x++)
274  {
275  // delete current data flow
276  delete y->second[x];
277 
278  } // for (x = 0; x < y->second.size(); x++)
279 
280  } // for (y = m_DataFlows.begin(); y != m_DataFlows.end(); y++)
281 
282 
283  // Bouml preserved body end 0005FB82
284 
285 } // CEVCStateMachine::CEVCState::~CEVCState() throw()
286 
287 
288 
289 
290 void CEVCStateMachine::CEVCState::Start() throw(::oETCS::DF::Error::CException)
291 {
292  // Bouml preserved body begin 00063282
293  decltype (m_DataFlows.begin()) x(m_DataFlows.find(m_pParent->m_CurrentApplicationLevel));
294  unsigned int y(0);
295 
296 
297 
298  // check, if data flow(s) exist for application level
299  if (x == m_DataFlows.end())
300  {
301  // throw exception
302  throw (::oETCS::DF::Error::CInternal("no corresponding application level in data flow"));
303 
304  } // if (x == m_DataFlows.end())
305 
306  // check, if another data flow is been executed
307  if (this->IsRunning() && m_CurrentDataFlow != x->second)
308  {
309  // throw exception
310  throw (::oETCS::DF::Error::CInternal("another data flow is currently be executed"));
311 
312  } // if (this->IsRunning() && m_CurrentDataFlow != x->second)
313 
314  // check, if no data flow is currently executed
315  if (m_CurrentDataFlow.empty())
316  {
317  // assign current data flow from map
318  m_CurrentDataFlow = x->second;
319 
320  // reset switch flag
321  m_bStateLevelSwitch = false;
322 
323  // reset number of locked threads
324  m_iLockedThreads = 0;
325 
326  // resize vector of threads
327  m_Threads.resize(m_CurrentDataFlow.size());
328 
329  // start all independent data flows
330  for (y = 0; y < m_CurrentDataFlow.size(); y++)
331  {
332  try
333  {
334  // set flag for newly entered data flow
336 
337  // create new thread
338  m_Threads[y] = (new ::std::thread(&::oETCS::DF::CEVCStateMachine::CEVCState::DataFlowThread, this, y));
339 
340 #ifdef __DEBUG_OUTPUT__
341  // DEBUG
342  ::std::cerr << std::this_thread::get_id() << " " << "StateThread ----> new state object started " << this << ::std::endl;
343 #endif
344 
345  } // try
346  catch (const ::std::bad_alloc&)
347  {
348  // delete all already created threads
349  for (y = 0; y < m_Threads.size(); y++)
350  {
351  // delete current thread
352  delete m_Threads[y];
353 
354  } // for (y = 0; y < m_Threads.size(); y++)
355 
356  // clear current data flow vector
357  m_CurrentDataFlow.clear();
358 
359  // clear vector with thread pointers
360  m_Threads.clear();
361 
362  // reset state/level switch flag
363  m_bStateLevelSwitch = false;
364 
365  // throw exception
366  throw (::oETCS::DF::Error::CInternal("not enough memory available for creating thread"));
367 
368  } // catch (const ::std::bad_alloc&)
369  catch (const ::std::exception& Exception)
370  {
371 #ifdef __DEBUG_OUTPUT__
372  // DEBUG
373  ::std::cerr << std::this_thread::get_id() << " " << "StateThread ----> uncaught ::std::exception " << Exception.what() << ::std::endl;
374 #endif
375 
376  } // catch (const ::std::exception& Exception)
377 
378  } // for (y = 0; y < m_CurrentDataFlow.size(); y++)
379 
380  // notify all observers via parent EVC state machine about new state/application level
381  m_pParent->Notify();
382 
383  // wait for all threads to finish and delete them
384  for (y = 0; y < m_Threads.size(); y++)
385  {
386  // check, if current thread is joinable
387  if (m_Threads[y]->joinable())
388  {
389 #ifdef __DEBUG_OUTPUT__
390  // DEBUG
391  ::std::cerr << std::this_thread::get_id() << " " << "CEVCState::Start() -----> waiting for thread " << y << ::std::endl;
392 #endif
393 
394  // wait for current thread
395  m_Threads[y]->join();
396 
397  } // if (m_Threads[y]->joinable())
398 
399  // delete current thread
400  delete m_Threads[y];
401 
402 #ifdef __DEBUG_OUTPUT__
403  // DEBUG
404  ::std::cerr << std::this_thread::get_id() << " " << "CEVCState::Start() -----> deleted thread " << y << ::std::endl;
405 #endif
406 
407  } // for (y = 0; y < m_Threads.size(); y++)
408 
409  // clear current data flow vector
410  m_CurrentDataFlow.clear();
411 
412  // clear vector with thread pointers
413  m_Threads.clear();
414 
415  // reset state/level switch flag
416  m_bStateLevelSwitch = false;
417 
418  // check, if exception ny data flows where stored in the stack
419  if (m_DataFlowExceptions.size() > 0)
420  {
421  // clear exception stack
422  m_DataFlowExceptions.clear();
423 
424  // throw exception
425  throw (::oETCS::DF::Error::CInternal("error during execution of data flow"));
426 
427  } // if (m_DataFlowExceptions.size() > 0)
428 
429  } // if (m_CurrentDataFlow.empty())
430 
431  // Bouml preserved body end 00063282
432 
433 } // void CEVCStateMachine::CEVCState::Start() throw(::oETCS::DF::Error::CException)
434 
435 
436 
437 
439 {
440  // Bouml preserved body begin 00063402
441  // check, if state is currently running
442  if (this->IsRunning())
443  {
444 #ifdef __DEBUG_OUTPUT__
445  // DEBUG
446  ::std::cerr << std::this_thread::get_id() << " " << "CEVCState::Stop() called " << ::std::endl;
447 #endif
448 
449  // use state/level switch to enable soft finishing
450  m_bStateLevelSwitch = true;
451 
452 #ifdef __DEBUG_OUTPUT__
453  // DEBUG
454  ::std::cerr << std::this_thread::get_id() << " " << "CEVCState::Stop() -----> waiting for this EVC state " << this << ::std::endl;
455 #endif
456 
457  // wait until all data flow threads notify their termination
458  while (this->IsRunning())
459  {
460  // yield
461  ::std::this_thread::yield();
462 
463  // use state/level switch to enable soft finishing (reset here to ensure notification)
464  m_bStateLevelSwitch = true;
465 
466  } // while (this->IsRunning())
467 
468 #ifdef __DEBUG_OUTPUT__
469  // DEBUG
470  ::std::cerr << std::this_thread::get_id() << " " << "CEVCState::Stop() -----> # threads after waiting " << m_Threads.size() << ::std::endl;
471 #endif
472 
473  } // if (this->IsRunning())
474 
475  // Bouml preserved body end 00063402
476 
477 } // void CEVCStateMachine::CEVCState::Stop() throw()
478 
479 
480 
481 
483 {
484  // Bouml preserved body begin 0006FB02
485  // return execution flag
486  return (!m_CurrentDataFlow.empty());
487  // Bouml preserved body end 0006FB02
488 
489 } // bool CEVCStateMachine::CEVCState::IsRunning() const throw()
490 
491 
492 
493 
495 {
496  // Bouml preserved body begin 00090202
497  bool bActive(false);
498  unsigned int x(0);
499  const unsigned int NUMBER_DATA_FLOWS(m_CurrentDataFlow.size());
500 
501 
502 
503  // process all data flows in this state for current application level
504  for (x = 0; x < NUMBER_DATA_FLOWS && !bActive; x++)
505  {
506  // process current data flow
507  bActive = m_CurrentDataFlow[x]->IsActiveFunctionBlock(pFunctionBlock);
508 
509  } // for (x = 0; x < NUMBER_DATA_FLOWS && !bActive; x++)
510 
511  // return active flag
512  return (bActive);
513  // Bouml preserved body end 00090202
514 
515 } // bool CEVCStateMachine::CEVCState::IsActiveFunctionBlock() const throw()
516 
517 
518 
519 
521 {
522  // Bouml preserved body begin 000C7082
523  bool bActive(false);
524  unsigned int x(0);
525  const unsigned int NUMBER_DATA_FLOWS(m_CurrentDataFlow.size());
526 
527 
528 
529  // process all data flows in this state for current application level
530  for (x = 0; x < NUMBER_DATA_FLOWS && !bActive; x++)
531  {
532  // process current data flow
533  bActive = m_CurrentDataFlow[x]->IsActiveFlow(pFlow);
534 
535  } // for (x = 0; x < NUMBER_DATA_FLOWS && !bActive; x++)
536 
537  // return active flag
538  return (bActive);
539  // Bouml preserved body end 000C7082
540 
541 } // bool CEVCStateMachine::CEVCState::IsActiveFlow() const throw()
542 
543 
544 
545 
546 ::std::vector< oETCS::DF::CTransition* > CEVCStateMachine::CEVCState::GetTransitions() const throw()
547 {
548  // Bouml preserved body begin 00086082
549  // return all transitions
550  return (m_Transitions);
551  // Bouml preserved body end 00086082
552 
553 } // oETCS::DF::CTransition CEVCStateMachine::CEVCState::GetTransitions() const throw()
554 
555 
556 
557 
558 ::std::vector< oETCS::DF::CEVCStateMachine::CEVCState::CDataFlow* > CEVCStateMachine::CEVCState::GetCurrentDataFlow() const throw()
559 {
560  // Bouml preserved body begin 00086182
561  // return current data flow(s)
562  return (m_CurrentDataFlow);
563  // Bouml preserved body end 00086182
564 
565 } // oETCS::DF::CEVCStateMachine::CEVCState::CDataFlow CEVCStateMachine::CEVCState::GetCurrentDataFlow() const throw()
566 
567 
568 
569 
570 void CEVCStateMachine::CEVCState::AddDataFlow(const std::string& ApplicationLevel, oETCS::DF::CEVCStateMachine::CEVCState::CDataFlow * const pDataFlow) throw()
571 {
572  // Bouml preserved body begin 0008CB82
573  // check, if pointer is valid
574  if (pDataFlow !=0)
575  {
576  // add pointer to vector in map
577  m_DataFlows[ApplicationLevel].push_back(pDataFlow);
578 
579  } // if (pDataFlow !=0)
580  // Bouml preserved body end 0008CB82
581 
582 } // void CEVCStateMachine::CEVCState::AddDataFlow() throw()
583 
584 
585 
586 
588 {
589  // Bouml preserved body begin 0008CB02
590  // check, if pointer is valid
591  if (pTransition !=0)
592  {
593  // add pointer to vector
594  m_Transitions.push_back(pTransition);
595 
596  } // if (m_pTransitions !=0)
597  // Bouml preserved body end 0008CB02
598 
599 } // void CEVCStateMachine::CEVCState::AddTransition() throw()
600 
601 
602 
603 
604 void CEVCStateMachine::CEVCState::DataFlowThread(const unsigned int & iIndex) throw()
605 {
606  // Bouml preserved body begin 00071582
607  ::std::mutex Mutex;
608  ::std::unique_lock< ::std::mutex > Lock(Mutex);
609  ::std::chrono::time_point< ::std::chrono::high_resolution_clock,
610  ::std::chrono::duration< long long,
611  ::std::chrono::high_resolution_clock::duration::period > > StartTime;
612  ::std::chrono::duration< long long,
613  ::std::chrono::high_resolution_clock::duration::period > SleepTime;
614  const ::std::chrono::duration< long long,
615  ::std::chrono::high_resolution_clock::duration::period > SAMPLE_TIME(::std::chrono::microseconds(__DATA_FLOW_SAMPLE_TIME__));
616  const ::oETCS::DF::CEVCTransition* pStateTransition(0);
617  unsigned int x(0);
618 
619 
620 
621 
622  // synchronise with all other threads at start
623  // check, if this is already last thread for synchronisation
624  if (m_iLockedThreads == (m_Threads.size() - 1))
625  {
626 
627  // notify all other threads to proceed
628  m_Barrier.notify_all();
629 
630  } // if (m_iLockedThreads == (m_Threads.size() - 1))
631  else
632  {
633  // increase number of locked threads
635 
636  // wait for all remaining executing threads
637  m_Barrier.wait(Lock);
638 
639  } // else
640 
641  // compute start time once
642  StartTime = ::std::chrono::high_resolution_clock::now();
643 
644  // execute thread until a state and/or level switch
645  while (!m_bStateLevelSwitch)
646  {
647  try
648  {
649  // execute related data flow once
650  m_CurrentDataFlow[iIndex]->Execute();
651 
652 #ifdef __DEBUG_OUTPUT__
653  // DEBUG
654  ::std::cerr << std::this_thread::get_id() << " " << "DataFlowThread ----> # executed data flow " << iIndex << ::std::endl;
655 #endif
656 
657  } // try
658  catch (const ::oETCS::DF::Error::CException& Exception)
659  {
660  // create and print error message to stderr
661  ::std::cerr << "Error while executing data flow # " << iIndex << ": " << Exception.what() << " in " << __FILE__ << " at line " << __LINE__ << ::std::endl;
662 
663  // store exception on stack
664  m_DataFlowExceptions.push_back(Exception);
665 
666  // stop execution of all threads by using the switch flag
667  m_bStateLevelSwitch = true;
668 
669  } // catch (const ::oETCS::DF::Error::CException& Exception)
670 
671 
672 #ifdef __DEBUG_OUTPUT__
673  // DEBUG
674  ::std::cerr << std::this_thread::get_id() << " " << "DataFlowThread ----> # locked threads " << m_iLockedThreads << " # threads " << m_Threads.size() << ::std::endl;
675 #endif
676 
677  // check, if this is already last thread for synchronisation
678  if (m_iLockedThreads == (m_Threads.size() - 1))
679  {
680  // check, if any transitions were placed on stack
681  if (m_TransitionStack.size() > 0)
682  {
683  // store very first pointer
684  pStateTransition = m_TransitionStack[0];
685 
686  // search all other transition on stack for higher priority
687  for (x = 1; x < m_TransitionStack.size(); x++)
688  {
689  // compare current priority with stored one
690  if (pStateTransition->GetPriority() < m_TransitionStack[x]->GetPriority())
691  {
692  // store current transition
693  pStateTransition = m_TransitionStack[x];
694 
695  } // if (pStateTransition->GetPriority() < m_TransitionStack[x]->GetPriority())
696 
697  } // for (x = 0; x < m_TransitionStack.size(); x++)
698 
699  // do sanity check of transition object
700  if (pStateTransition->GetStartState() != this)
701  {
702  // print error message to stderr
703  ::std::cerr << "In file " << __FILE__ << " at line " << __LINE__ << ": activated transition object has false start state" << ::std::endl;
704 
705  } // if (pStateTransition->GetStartState() != this)
706 
707  // set pointer to new state in parent state machine
708  m_pParent->m_pCurrentState = pStateTransition->GetTargetState();
709 
710 #ifdef __DEBUG_OUTPUT__
711  // DEBUG
712  ::std::cerr << std::this_thread::get_id() << " " << "DataFlowThread ----> switch to new state object " << m_pParent->m_pCurrentState << ::std::endl;
713 #endif
714 
715  // activate flag for state/level switch
716  m_bStateLevelSwitch = true;
717 
718  // clear transition stack
719  m_TransitionStack.clear();
720 
721  } // if (m_TransitionStack.size() > 0)
722 
723  // reset the number of locked threads
724  m_iLockedThreads = 0;
725 
726  // reset entered flag
728 
729  // notify all other threads to proceed
730  m_Barrier.notify_all();
731 
732  } // if (m_iLockedThreads == (m_Threads.size() - 1))
733  else
734  {
735  // increase number of locked threads
737 
738  // wait for all remaining executing threads
739  m_Barrier.wait(Lock);
740 
741  } // else
742 
743 
744  // compute sleep time by execution time until now
745  SleepTime = SAMPLE_TIME - (::std::chrono::high_resolution_clock::now() - StartTime);
746 
747  // check, if sample time was no exceeded
748  if (SleepTime.count() >= 0 )
749  {
750  // put thread to sleep
751  ::std::this_thread::sleep_for(SleepTime);
752 
753  } // if (SleepTime.count() >= 0 )
754  else
755  {
756  // print warning to stderr
757  ::std::cerr << "In file " << __FILE__ << " in line " << __LINE__ << ": sample time exceeded in thread" << std::endl;
758 
759  } // else
760 
761  // calculate next start time point to avoid global drifts
762  StartTime += SAMPLE_TIME;
763 
764  } // while (!m_bStateLevelSwitch)
765 
766 #ifdef __DEBUG_OUTPUT__
767  // DEBUG
768  ::std::cerr << std::this_thread::get_id() << " " << "DataFlowThread ----> execution self stopped (end of while)" << ::std::endl;
769 #endif
770 
771  // Bouml preserved body end 00071582
772 
773 } // void CEVCStateMachine::CEVCState::DataFlowThread() throw()
774 
775 
776 
777 
779 :m_bStarted(false),
781  m_Transitions(0),
782  m_FunctionBlocks(0),
784  m_pCurrentState(0),
785  m_pThread(0)
786 {
787  // Bouml preserved body begin 00064E02
788  // empty constructor
789  // Bouml preserved body end 00064E02
790 
791 } // CEVCStateMachine::CEVCStateMachine() throw()
792 
793 
794 
795 
797 {
798  // Bouml preserved body begin 00064E82
799  unsigned int x(0);
800  decltype (m_Flows.begin()) f;
801 
802 
803  // check, if a current state is available and executing
805  {
806  // stop current state
807  this->Stop();
808 
809  } // if (m_pCurrentState != 0 && m_pCurrentState->IsRunning())
810 
811  // delete all state objects
812  for (x = 0; x < m_AvailableStates.size(); x++)
813  {
814  // delete current state object
815  delete m_AvailableStates[x];
816 
817  } // for (x = 0; x < m_AvailableStates.size(); x++)
818 
819  // delete all transition objects
820  for (x = 0; x < m_Transitions.size(); x++)
821  {
822  // delete current transition object
823  delete m_Transitions[x];
824 
825  } // for (x = 0; x < m_Transitions.size(); x++)
826 
827  // delete all language objects
828  for (x = 0; x < m_Language.size(); x++)
829  {
830  // delete current language object
831  delete m_Language[x];
832 
833  } // for (x = 0; x < m_Language.size(); x++)
834 
835  // delete all flows objetcs
836  for (f = m_Flows.begin(); f != m_Flows.end(); f++)
837  {
838  // delete current flow object
839  delete *f;
840 
841  } // for (f = m_Flows.begin(); f != m_Flows.end(); f++)
842 
843  // Bouml preserved body end 00064E82
844 
845 } // CEVCStateMachine::~CEVCStateMachine() throw()
846 
847 
848 
849 
851 {
852  // Bouml preserved body begin 0008CD02
853  // check, if pointer is valid
854  if (pFunctionBlock != 0)
855  {
856  // add pointer to local vector
857  m_FunctionBlocks.push_back(pFunctionBlock);
858 
859  } // if (pFunctionBlock != 0)
860  // Bouml preserved body end 0008CD02
861 
862 } // void CEVCStateMachine::AddFunctionBlock() throw()
863 
864 
865 
866 
868 {
869  // Bouml preserved body begin 0008CC02
870  // check, if pointer is valid
871  if (pState != 0)
872  {
873  // add pointer to local vector
874  m_AvailableStates.push_back(pState);
875 
876  } // if (pState != 0)
877  // Bouml preserved body end 0008CC02
878 
879 } // void CEVCStateMachine::AddState() throw()
880 
881 
882 
883 
885 {
886  // Bouml preserved body begin 0008CC82
887  // check, if pointer is valid
888  if (pTransition != 0)
889  {
890  // add pointer to local vector
891  m_Transitions.push_back(pTransition);
892 
893  } // if (pTransition != 0)
894  // Bouml preserved body end 0008CC82
895 
896 } // void CEVCStateMachine::AddTransition() throw()
897 
898 
899 
900 
901 void CEVCStateMachine::AddLanguage(oETCS::DF::CLanguage * const pLanguage) throw()
902 {
903  // Bouml preserved body begin 000A6C82
904  // check, if pointer is valid
905  if (pLanguage != 0)
906  {
907  // add pointer to local vector
908  m_Language.push_back(pLanguage);
909 
910  } // if (pLanguage != 0)
911  // Bouml preserved body end 000A6C82
912 
913 } // void CEVCStateMachine::AddLanguage() throw()
914 
915 
916 
917 
919 {
920  // Bouml preserved body begin 000C8A02
921  // check, if pointer is valid
922  if (pFlow != 0)
923  {
924  // add pointer to local vector
925  m_Flows.push_back(pFlow);
926 
927  } // if (pLanguage != 0)
928  // Bouml preserved body end 000C8A02
929 
930 } // void CEVCStateMachine::AddFlow() throw()
931 
932 
933 
934 
936 {
937  // Bouml preserved body begin 000C3A02
938  // check, if pointer to observer is valid
939  if (pDMIObserver != nullptr)
940  {
941  // add current pointer to vector
942  m_Observers.push_back(pDMIObserver);
943 
944  } // if (pDMIObserver != nullptr)
945  // Bouml preserved body end 000C3A02
946 
947 } // void CEVCStateMachine::AttachObserver() throw()
948 
949 
950 
951 
953 {
954  // Bouml preserved body begin 000C3A82
955  decltype (m_Observers.begin()) o;
956 
957 
958 
959  // check, if pointer to observer is valid
960  if (pDMIObserver != nullptr)
961  {
962  // try to find observer in vector
963  for (o = m_Observers.begin(); o != m_Observers.end(); o++)
964  {
965  // check, if current pointer matches
966  if (*o == pDMIObserver)
967  {
968  // remove current entry from vector
969  o = m_Observers.erase(o) - 1;
970 
971  } // if (*o == pDMIObserver)
972 
973  } // for (o = m_Observers.begin(); o != m_Observers.end(); o++)
974 
975  } // if (pDMIObserver != nullptr)
976  // Bouml preserved body end 000C3A82
977 
978 } // void CEVCStateMachine::DetachObserver() throw()
979 
980 
981 
982 
984 {
985  // Bouml preserved body begin 00072F02
986  // return pointer to current state
987  return (m_pCurrentState);
988  // Bouml preserved body end 00072F02
989 
990 } // oETCS::DF::CEVCStateMachine::CEVCState CEVCStateMachine::GetActiveState() const throw()
991 
992 
993 
994 
995 ::std::vector< oETCS::DF::CEVCTransition* > CEVCStateMachine::GetTransitions() const throw()
996 {
997  // Bouml preserved body begin 00072F82
998  // return vector with all transitions
999  return (m_Transitions);
1000  // Bouml preserved body end 00072F82
1001 
1002 } // ::std::vector< oETCS::DF::CEVCTransition* > CEVCStateMachine::GetTransitions() const throw()
1003 
1004 
1005 
1006 
1007 ::std::vector< oETCS::DF::CEVCStateMachine::CEVCState* > CEVCStateMachine::GetStates() const throw()
1008 {
1009  // Bouml preserved body begin 00089782
1010  // return vector with all states
1011  return (m_AvailableStates);
1012  // Bouml preserved body end 00089782
1013 
1014 } // ::std::vector< oETCS::DF::CEVCStateMachine::CEVCState* > CEVCStateMachine::GetStates() const throw()
1015 
1016 
1017 
1018 
1020 {
1021  // Bouml preserved body begin 000C3B02
1022  ::oETCS::DF::CDMISubject* pCurrentDMI(nullptr);
1023 
1024 
1025 
1026  // check, if current state is valid
1027  if (m_pCurrentState != nullptr)
1028  {
1029  // check, if current state has at least one data flow object
1030  if (not m_pCurrentState->GetCurrentDataFlow().empty())
1031  {
1032  // set current DMI from first data flow
1033  pCurrentDMI = m_pCurrentState->GetCurrentDataFlow()[0]->m_pDMI;
1034 
1035  } // if (not m_pCurrentState->GetCurrentDataFlow().empty())
1036 
1037  } // if (m_pCurrentState != nullptr)
1038 
1039  // return pointer to current DMI subject
1040 
1041  return (pCurrentDMI);
1042  // Bouml preserved body end 000C3B02
1043 
1044 } // oETCS::DF::CDMISubject CEVCStateMachine::GetCurrentDMI() throw()
1045 
1046 
1047 
1048 
1049 void CEVCStateMachine::Start(oETCS::DF::CEVCStateMachine::CEVCState * const pStartState, const std::string & ApplicationLevel) throw(::oETCS::DF::Error::CException)
1050 {
1051  // Bouml preserved body begin 0006FA02
1052  unsigned int x(0);
1053  bool bFound(false);
1054 
1055 
1056  // check, if a current state is valid
1057  if (pStartState == 0)
1058  {
1059  // throw exception
1060  throw (::oETCS::DF::Error::CInternal("pointer to start state is not valid"));
1061 
1062  } // if (pStartState == 0)
1063 
1064  // check, if state machine is not already running
1065  if (m_pCurrentState == 0 || !m_pCurrentState->IsRunning())
1066  {
1067  // try to find start state in available states
1068  for (x = 0; x < m_AvailableStates.size() && !bFound; x++)
1069  {
1070  // compare current state
1071  if (m_AvailableStates[x] == pStartState)
1072  {
1073  // set found flag to true
1074  bFound = true;
1075 
1076  } // if (m_AvailableStates[x] == pStartState)
1077 
1078  } // for (x = 0; x < m_AvailableStates.size() && !bFound; x++)
1079 
1080  // check, if start state is included in available states
1081  if (!bFound)
1082  {
1083  // throw exception
1084  throw (::oETCS::DF::Error::CInternal("start state is not listed in available states"));
1085 
1086  } // if (!bFound)
1087 
1088  // set start flag to started
1089  m_bStarted = true;
1090 
1091  // set current application level
1092  m_CurrentApplicationLevel = ApplicationLevel;
1093 
1094  // set current state
1095  m_pCurrentState = pStartState;
1096 
1097  try
1098  {
1099  // start thread for EVC state execution
1100  m_pThread = new ::std::thread(&::oETCS::DF::CEVCStateMachine::StateThread, this);
1101 
1102  } // try
1103  catch (...)
1104  {
1105  // set start flag to stopped
1106  m_bStarted = false;
1107 
1108  // delete thread object, if exists
1109  delete m_pThread;
1110 
1111  // set current state to invalid
1112  m_pCurrentState = 0;
1113 
1114  // throw exception
1115  throw (::oETCS::DF::Error::CInternal("could not create EVC state thread object"));
1116 
1117  } // catch (...)
1118 
1119  } // if (m_pCurrentState == 0 || !m_pCurrentState->IsRunning())
1120  // Bouml preserved body end 0006FA02
1121 
1122 } // void CEVCStateMachine::Start() throw(::oETCS::DF::Error::CException)
1123 
1124 
1125 
1126 
1127 void CEVCStateMachine::Stop() throw(::oETCS::DF::Error::CException)
1128 {
1129  // Bouml preserved body begin 0006FA82
1130  // check, if a current state is available
1131  if (m_pCurrentState == 0)
1132  {
1133  // throw exception
1134  throw (::oETCS::DF::Error::CInternal("no current state available"));
1135 
1136  } // if (m_pCurrentState == 0)
1137 
1138  // check, if current state is already running
1139  if (m_pCurrentState->IsRunning())
1140  {
1141 #ifdef __DEBUG_OUTPUT__
1142  // DEBUG
1143  ::std::cerr << std::this_thread::get_id() << " " << "CEVCStateMachine::Stop() called " << ::std::endl;
1144 #endif
1145 
1146  // explicitly set the state machine to stop
1147  m_bStarted = false;
1148 
1149  // start execution of current state
1150  m_pCurrentState->Stop();
1151 
1152  // check, if thread is joinable
1153  if (m_pThread->joinable())
1154  {
1155 #ifdef __DEBUG_OUTPUT__
1156  // DEBUG
1157  ::std::cerr << std::this_thread::get_id() << " " << "CEVCStateMachine::Stop() -----> waiting for thread" << ::std::endl;
1158 #endif
1159 
1160  // wait for thread to terminate
1161  m_pThread->join();
1162 
1163  } //if (m_pThread->joinable())
1164 
1165  // finally delete thread object
1166  delete m_pThread;
1167 
1168  // reset thread pointer
1169  m_pThread = 0;
1170 
1171 #ifdef __DEBUG_OUTPUT__
1172  // DEBUG
1173  ::std::cerr << std::this_thread::get_id() << " " << "CEVCStateMachine::Stop() -----> all stopped" << ::std::endl;
1174 #endif
1175 
1176  } // if (m_pCurrentState->IsRunning())
1177  // Bouml preserved body end 0006FA82
1178 
1179 } // void CEVCStateMachine::Stop() throw(::oETCS::DF::Error::CException)
1180 
1181 
1182 
1183 
1185 {
1186  // Bouml preserved body begin 000C3882
1187  decltype (m_Observers.begin()) o;
1188 
1189 
1190  // proceed all attached observers
1191  for (o = m_Observers.begin(); o != m_Observers.end(); o++)
1192  {
1193  // call update on current observer
1194  (*o)->Update();
1195 
1196  } // for (o = m_Observers.begin(); o != m_Observers.end(); o++)
1197  // Bouml preserved body end 000C3882
1198 
1199 } // void CEVCStateMachine::Notify() throw()
1200 
1201 
1202 
1203 
1205 {
1206  // Bouml preserved body begin 0008E882
1207  // re-execute current state (after state or level switch). while this state machine is set to running
1208  while (m_bStarted)
1209  {
1210 
1211 #ifdef __DEBUG_OUTPUT__
1212  // DEBUG output
1213  ::std::cerr << std::this_thread::get_id() << " " << "StateThread ----> about to start state in level " << m_CurrentApplicationLevel << ::std::endl;
1214 #endif
1215 
1216  try
1217  {
1218  // start execution of current state
1220 
1221  } // try
1222  catch (const ::oETCS::DF::Error::CException& Exception)
1223  {
1224  // set start flag to stopped
1225  m_bStarted = false;
1226 
1227  // create and print error message to stderr
1228  ::std::cerr << "Error while executing current EVC state: " << Exception.what() << " in " << __FILE__ << " at line " << __LINE__ << " and no fault state available!" << ::std::endl;
1229 
1230  } // catch (const ::oETCS::DF::Error::CException& Exception)
1231 
1232 #ifdef __DEBUG_OUTPUT__
1233  // DEBUG
1234  ::std::cerr << std::this_thread::get_id() << " " << "StateThread ----> execution of current state stopped" << ::std::endl;
1235 #endif
1236 
1237  } // while (m_bStarted)
1238  // Bouml preserved body end 0008E882
1239 
1240 } // void CEVCStateMachine::StateThread() throw()
1241 
1242 
1243 
1244 
1245 CEVCTransition::CEVCTransition(oETCS::DF::CEVCCondition * const pCondition, oETCS::DF::CEVCStateMachine::CEVCState * const pStartState, oETCS::DF::CEVCStateMachine::CEVCState * const pTargetState, const unsigned int & iPriority) throw()
1246 :m_pCondition(pCondition),
1247  m_pStartState(pStartState),
1248  m_pTargetState(pTargetState),
1249  m_iPriority(iPriority)
1250 {
1251  // Bouml preserved body begin 00068682
1252  // add this instance to parent state machine
1253  m_pStartState->m_pParent->AddTransition(this);
1254  // Bouml preserved body end 00068682
1255 
1256 } // CEVCTransition::CEVCTransition() throw()
1257 
1258 
1259 
1260 
1262 {
1263  // Bouml preserved body begin 00068702
1264  // empty destructor
1265  // Bouml preserved body end 00068702
1266 
1267 } // CEVCTransition::~CEVCTransition() throw()
1268 
1269 
1270 
1271 
1273 {
1274  // Bouml preserved body begin 00073002
1275  // return pointer to related condition object
1276  return (m_pCondition);
1277  // Bouml preserved body end 00073002
1278 
1279 } // oETCS::DF::CEVCCondition CEVCTransition::GetCondition() const throw()
1280 
1281 
1282 
1283 
1285 {
1286  // Bouml preserved body begin 00073082
1287  // return pointer to related start state object
1288  return (m_pStartState);
1289  // Bouml preserved body end 00073082
1290 
1291 } // oETCS::DF::CEVCStateMachine::CEVCState CEVCTransition::GetStartState() const throw()
1292 
1293 
1294 
1295 
1297 {
1298  // Bouml preserved body begin 00073102
1299  // return pointer to related target state object
1300  return (m_pTargetState);
1301  // Bouml preserved body end 00073102
1302 
1303 } // oETCS::DF::CEVCStateMachine::CEVCState CEVCTransition::GetTargetState() const throw()
1304 
1305 
1306 
1307 
1308 unsigned int CEVCTransition::GetPriority() const throw()
1309 {
1310  // Bouml preserved body begin 00073182
1311  // return numerical priority
1312  return (m_iPriority);
1313  // Bouml preserved body end 00073182
1314 
1315 } // unsigned int CEVCTransition::GetPriority() const throw()
1316 
1317 
1318 
1319 
1321 :m_pStateMachine(pStateMachine)
1322 {
1323  // Bouml preserved body begin 00064F02
1324  // check, if pointer to state machien is valid
1325  if (pStateMachine != nullptr)
1326  {
1327  // add this instance to state machine
1328  m_pStateMachine->AddFunctionBlock(this);
1329 
1330  } // if (pStateMachine != nullptr)
1331  // Bouml preserved body end 00064F02
1332 
1333 } // CFunctionBlock::CFunctionBlock() throw()
1334 
1335 
1336 
1337 
1339 {
1340  // Bouml preserved body begin 000DDC82
1341  // empty destructor
1342  // Bouml preserved body end 000DDC82
1343 
1344 } // CFunctionBlock::~CFunctionBlock() throw()
1345 
1346 
1347 
1348 
1350 {
1351  // Bouml preserved body begin 00068602
1352  // return this instance
1353  return (*this);
1354  // Bouml preserved body end 00068602
1355 
1356 } // oETCS::DF::CFunctionBlock CFunctionBlock::operator=() throw()
1357 
1358 
1359 
1360 
1362 :m_pStateMachine(pStateMachine)
1363 {
1364  // Bouml preserved body begin 000C7002
1365  // Bouml preserved body end 000C7002
1366 
1367 } // CAbstractFlow::CAbstractFlow() throw()
1368 
1369 
1370 
1371 
1373 {
1374  // Bouml preserved body begin 000C5482
1375  // empty destructor (only needed for polymorphism)
1376  // Bouml preserved body end 000C5482
1377 
1378 } // CAbstractFlow::~CAbstractFlow() throw()
1379 
1380 
1381 
1382 
1383 CBitFlow::CBitFlow(oETCS::DF::CStorage * const pInput, oETCS::DF::CEVCStateMachine * const pStateMachine) throw()
1384 :CAbstractFlow(pStateMachine),
1385  m_pInput(pInput)
1386 {
1387  // Bouml preserved body begin 000CBD82
1388  // empty constructor
1389  // Bouml preserved body end 000CBD82
1390 
1391 } // CBitFlow::CBitFlow() throw()
1392 
1393 
1394 
1395 
1396 void CBitFlow::operator=(const oETCS::DF::CStorage& Value) throw()
1397 {
1398  // Bouml preserved body begin 000CBE02
1399  // check, if this flow is part of the current data flow (active state nullptr means test case)
1400  if (m_pStateMachine->GetActiveState() == nullptr || m_pStateMachine->GetActiveState()->IsActiveFlow(this))
1401  {
1402  // switch last input type
1403  switch (Value.GetLastInputType())
1404  {
1406  // copy value to boolean input of connected storage object
1407  m_pInput->m_bBoolInput = Value.m_bBoolInput();
1408 
1409  break;
1410 
1411 
1413  // copy value to double input of connected storage object
1414  m_pInput->m_dDoubleInput = Value.m_dDoubleInput();
1415 
1416  break;
1417 
1418 
1420  // copy value to double array input of connected storage object
1421  m_pInput->m_DoubleArrayInput = Value.m_DoubleArrayInput();
1422 
1423  break;
1424 
1425 
1427  // copy value to integer input of connected storage object
1428  m_pInput->m_iIntInput = Value.m_iIntInput();
1429 
1430  break;
1431 
1432 
1434  // copy value to string input of connected storage object
1435  m_pInput->m_StringInput = Value.m_StringInput();
1436 
1437  break;
1438 
1439  } // switch (Value.GetLastInputType())
1440 
1441  } // if (m_pStateMachine->GetActiveState() == nullptr || m_pStateMachine->GetActiveState()->IsActiveFlow(this))
1442  // Bouml preserved body end 000CBE02
1443 
1444 } // void CBitFlow::operator=() throw()
1445 
1446 
1447 
1448 
1450 {
1451  // Bouml preserved body begin 000DF602
1452  // return the pointer to the input instance of this flow
1453  return (m_pInput);
1454  // Bouml preserved body end 000DF602
1455 
1456 } // oETCS::DF::CStorage* CBitFlow::operator->() throw()
1457 
1458 
1459 
1460 
1461 CLevelCondition::CLevelCondition(oETCS::DF::CEVCStateMachine * const pStateMachine, const std::string & ApplicationLevel) throw()
1462 :CFunctionBlock(pStateMachine),
1463  m_bLevelSwitch(false),
1464  m_TargetApplicationLevel(ApplicationLevel)
1465 {
1466  // Bouml preserved body begin 00066B82
1467  // empty constructor
1468  // Bouml preserved body end 00066B82
1469 
1470 } // CLevelCondition::CLevelCondition() throw()
1471 
1472 
1473 
1474 
1476 {
1477  // Bouml preserved body begin 00066C02
1478  // empty destructor
1479  // Bouml preserved body end 00066C02
1480 
1481 } // CLevelCondition::~CLevelCondition() throw()
1482 
1483 
1484 
1485 
1486 void CLevelCondition::Calculate() throw(::oETCS::DF::Error::CException)
1487 {
1488  // Bouml preserved body begin 00066B02
1489  // check, if application level switch was activated
1490  if (m_bLevelSwitch())
1491  {
1492  // set the new application level in parent EVC state machine
1493  //m_pStateMachine->SetApplicationLevel(m_TargetApplicationLevel);
1494  m_pStateMachine->m_CurrentApplicationLevel = m_TargetApplicationLevel;
1495 
1496 #ifdef __DEBUG_OUTPUT__
1497  // DEBUG
1498  ::std::cerr << std::this_thread::get_id() << " " << "CLevelCondition::Calculate() -----> set new application level: " << m_pStateMachine->m_CurrentApplicationLevel << ::std::endl;
1499 #endif
1500 
1501  // activate level/state switch in current state
1502  m_pStateMachine->GetActiveState()->m_bStateLevelSwitch = true;
1503 
1504  } // if (m_bLevelSwitch())
1505  // Bouml preserved body end 00066B02
1506 
1507 } // void CLevelCondition::Calculate() throw(::oETCS::DF::Error::CException)
1508 
1509 
1510 
1511 
1513 :CFunctionBlock(pStateMachine),
1514  m_bGuard(false)
1515 {
1516  // Bouml preserved body begin 0005F802
1517  // empty constructor
1518  // Bouml preserved body end 0005F802
1519 
1520 } // CEVCCondition::CEVCCondition() throw()
1521 
1522 
1523 
1524 
1526 {
1527  // Bouml preserved body begin 0005F882
1528  // empty destructor
1529  // Bouml preserved body end 0005F882
1530 
1531 } // CEVCCondition::~CEVCCondition() throw()
1532 
1533 
1534 
1535 
1536 void CEVCCondition::Calculate() throw(::oETCS::DF::Error::CException)
1537 {
1538  // Bouml preserved body begin 00065102
1539  unsigned int x;
1540  const unsigned int NUMBER_TRANSITIONS(m_pStateMachine->GetTransitions().size());
1541  bool bFound(false);
1542 
1543  // check, if guard was activated
1544  if (m_bGuard())
1545  {
1546  // try find corresponding transition object in EVC state machine
1547  for (x = 0; x < NUMBER_TRANSITIONS && !bFound; x++)
1548  {
1549  // check if current transition is connected with current condition and current state
1550  if (m_pStateMachine->GetTransitions()[x]->GetCondition() == this && m_pStateMachine->GetTransitions()[x]->GetStartState() == m_pStateMachine->GetActiveState())
1551  {
1552  // add pointer to transition to stack
1553  m_pStateMachine->GetActiveState()->m_TransitionStack.push_back(m_pStateMachine->GetTransitions()[x]);
1554 
1555  // set found flag
1556  bFound = true;
1557 
1558  } // if ((*m_pStateMachine->GetTransitions())[x].GetCondition() == this && (*m_pStateMachine->GetTransitions())[x].GetStartState() == m_pStateMachine->GetActiveState())
1559 
1560  } // for (x = 0; x < NUMBER_TRANSITIONS && !bFound; x++)
1561 
1562  // finally reset guard
1563  m_bGuard = false;
1564 
1565  // call method to reset modified flag
1566  m_bGuard.IsModified();
1567 
1568  // check if a matching transition was found
1569  if (!bFound)
1570  {
1571  // throw exception
1572  throw (::oETCS::DF::Error::CInternal("no matching EVC transition found for EVC condition"));
1573 
1574  } // if (!bFound)
1575 
1576  } // if (m_bGuard())
1577  // Bouml preserved body end 00065102
1578 
1579 } // void CEVCCondition::Calculate() throw(::oETCS::DF::Error::CException)
1580 
1581 
1582 
1583 
1584 CDMISubject::CDMISubject(const ::std::vector< oETCS::DF::CDMIInput * >& Inputs, const ::std::vector< oETCS::DF::CDMIOutput * >& Outputs) throw()
1585 :m_Inputs(Inputs),
1586  m_Outputs(Outputs)
1587 {
1588  // Bouml preserved body begin 0006DF82
1589  // empty constructor
1590  // Bouml preserved body end 0006DF82
1591 
1592 } // CDMISubject::CDMISubject() throw()
1593 
1594 
1595 
1596 
1598 {
1599  // Bouml preserved body begin 0006E002
1600  // empty descructor
1601  // Bouml preserved body end 0006E002
1602 
1603 } // CDMISubject::~CDMISubject() throw()
1604 
1605 
1606 
1607 
1609 :m_pStateMachine(pStateMachine)
1610 {
1611  // Bouml preserved body begin 000C3982
1612  // Bouml preserved body end 000C3982
1613 
1614 } // CDMIObserver::CDMIObserver() throw()
1615 
1616 
1617 
1618 
1619 ::std::ostream& operator<<(::std::ostream & OutStream, const ::std::vector< double >& Vector) throw()
1620 {
1621  // Bouml preserved body begin 000E7702
1622  decltype (Vector.begin()) x;
1623 
1624 
1625 
1626 
1627  // output starting of vector
1628  OutStream << "[";
1629 
1630  // output vector element-wise
1631  for (x = Vector.begin(); x != Vector.end(); x++)
1632  {
1633  // output current element
1634  OutStream << *x << "; ";
1635 
1636  } // for (x = Vector.begin(); x != Vector.end(); x++)
1637 
1638  // output end of vector
1639  OutStream << "]";
1640 
1641 
1642  // return reference to out stream
1643  return (OutStream);
1644  // Bouml preserved body end 000E7702
1645 
1646 } // ::std::ostream& operator<<() throw()
1647 
1648 
1649 
1650 
1651 
1652 
1653 } // namespace oETCS::DF
1654 
1655 } // namespace oETCS

Copyright (C) 2010-2012 Johannes Feuser (feuser@uni-bremen.de)
The openETCS library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
The openETCS library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with the openETCS library. If not, see "http://www.gnu.org/licenses/.