openETCS
case study for the European Train Control System developed for the authors dissertation
EVCStateMachine.h
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 #ifndef __OETCS_DF_EVCSTATEMACHINE_H__
26 #define __OETCS_DF_EVCSTATEMACHINE_H__
27 
28 
29 #include <chrono>
30 #include <iostream>
31 #include <algorithm>
32 
33 #include <string>
34 #include <vector>
35 #include "Error/ExceptionTypes.h"
36 #include <map>
37 #include <condition_variable>
38 #include <thread>
39 #include "Configuration.h"
40 #include <mutex>
41 #include <ostream>
42 
43 
44 namespace oETCS { namespace UT { class CEVCStateMachine; } }
45 namespace oETCS { namespace UT { class CFunctionBlock; } }
46 namespace oETCS { namespace DF { class CFunctionBlock; } }
47 namespace oETCS { namespace DF { class CAbstractFlow; } }
48 namespace oETCS { namespace DF { class CEVCCondition; } }
49 namespace oETCS { namespace DF { class CEVCStateMachine; } }
50 namespace oETCS { namespace DF { class CDMIObserver; } }
51 namespace oETCS { namespace DF { class CDMISubject; } }
52 namespace oETCS { namespace DF { class CEVCTransition; } }
53 namespace oETCS { namespace DF { class CLevelCondition; } }
54 
55 
56 namespace oETCS { namespace DF { class CTransition; } }
57 namespace oETCS { namespace DF { class CLanguage; } }
58 namespace oETCS { namespace DF { class CStorage; } }
59 namespace oETCS { namespace DF { class CDMIInput; } }
60 namespace oETCS { namespace DF { class CDMIOutput; } }
61 
62 
63 namespace oETCS {
64 
65 namespace DF {
66 
67 
68 /*!
69  * \brief EVC state machine class
70  */
72 {
73  public:
74  /*!
75  * \brief EVC state class executed by the EVC state machine
76  *
77  * Is a nested class to gain direct access to its parent class.
78  */
79  class CEVCState
80  {
81  public:
82  /*!
83  * \brief data flow class for executing data flows and embedded control flows
84  *
85  * Is a nested class to gain direct access to its parent class.
86  */
87  class CDataFlow
88  {
89  public:
90  /*!
91  * \brief general constructor
92  *
93  * Parameterises the data flow with all constant members.
94  * The data flow object takes over the posession of the passed DMI object.
95  *
96  * \param[in] pState pointer to the parent EVC state object
97  * \param[in] ApplicationLevel literal name of the application level in which this state object is executed
98  * \param[in] FunctionBlocks vector with pointers to all function block objects
99  * \param[in] Flows vector with pointers to all concrete CFlow/function block connection objects
100  * \param[in] pDMI pointer to the DMI object of the data flow
101  * \param[in] pFaultState optional pointer to the target state in case of a fault
102  */
103  explicit CDataFlow(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, CEVCState * const pFaultState = 0) throw();
104 
105 
106 
107  /*!
108  * \brief destructor
109  */
110  virtual ~CDataFlow() throw();
111 
112 
113 
114  /*!
115  * \brief gets all function block objects
116  *
117  * \return vector with pointers all function block objects
118  */
119  ::std::vector< oETCS::DF::CFunctionBlock* > GetFunctionBlocks() const throw();
120 
121 
122 
123  /*!
124  * \brief returns true, if a CFunctionBlock objects is active in a data flow
125  *
126  * \param[in] pFunctionBlock pointer to a function block object to be testetd
127  * \return active state flag
128  */
129  bool IsActiveFunctionBlock(const oETCS::DF::CFunctionBlock * const pFunctionBlock) const throw();
130 
131 
132 
133  /*!
134  * \brief returns true, if a CFlow object is active in a data flow
135  *
136  * \param[in] pFlow pointer to a concerete flow object
137  * \return active flow flag
138  */
139  bool IsActiveFlow(const oETCS::DF::CAbstractFlow * const pFlow) const throw();
140 
141 
142 
143  /*!
144  * \brief executes all includes CFunctionBlock order (by their order) for one sample point
145  */
146  void Execute() throw(::oETCS::DF::Error::CException);
147 
148 
149 
150  /*!
151  * \brief pointer to DMI widget of data flow
152  */
154 
155 
156 
157 
158  private:
159  /*!
160  * \brief vector of pointers to all function blocks used in this data flow in their execution order
161  */
162  const ::std::vector< oETCS::DF::CFunctionBlock* > m_FunctionBlocks;
163 
164 
165 
166  /*!
167  * \brief vector with pointer to all flows/connections used in a data flow
168  */
169  ::std::vector< oETCS::DF::CAbstractFlow* > m_Flows;
170 
171 
172 
173  /*!
174  * \brief pointer to the parent EVC state object
175  */
177 
178 
179 
180  /*!
181  * \brief optinal pointer to a EVC state object to which is switched in case of a fault
182  */
184 
185 
186 
187 
188  }; // class CDataFlow
189 
190 
191 
192 
193  /*!
194  * \brief general constructor
195  *
196  * Parameterises the EVC state with all constant members.
197  * The EVC state object takes over the posession of all variables/memory
198  * passed by pointer.
199  *
200  * \param[in] pParent pointer to the parent EVC state machine object
201  */
202  CEVCState(CEVCStateMachine * const pParent) throw();
203 
204 
205 
206  /*!
207  * \brief destructor
208  */
209  virtual ~CEVCState() throw();
210 
211 
212 
213  /*!
214  * \brief starts the permanent execution of the related data flow
215  *
216  * If the number of independent CDataFLow objects for the current application level is
217  * greater than 1, this method will start for each additional group a additinal thread,
218  * while this method always is blocking.
219  * If a CEVCState is executed under the same parent CEVCStateMachine object, this will be
220  * stopped before by its CEVCState::Stop() method.
221  *
222  */
223  void Start() throw(::oETCS::DF::Error::CException);
224 
225 
226 
227  /*!
228  * \brief stops the execution the data flow by the underlying CFunctionBlock objects
229  *
230  * In the case of more than 1 group of independent CDatatFlow objects
231  * this method terminates all related threads by wating for the current
232  * execution sample to finish.
233  */
234  void Stop() throw();
235 
236 
237 
238  /*!
239  * \brief returns the running flag
240  *
241  * \return true, if is executing
242  */
243  bool IsRunning() const throw();
244 
245 
246 
247  /*!
248  * \brief returns true, if a CFunctionBlock objects is active in an EVC state
249  *
250  * \param[in] pFunctionBlock pointer to a function block object to be testetd
251  * \return active state flag
252  */
253  bool IsActiveFunctionBlock(oETCS::DF::CFunctionBlock * const pFunctionBlock) const throw();
254 
255 
256 
257  /*!
258  * \brief returns true, if a CFlowobjects is active in an EVC state
259  *
260  * \param[in] pFlow pointer to the concrete CFlow object to be testetd
261  * \return active state flag
262  */
263  bool IsActiveFlow(oETCS::DF::CAbstractFlow * const pFlow) const throw();
264 
265 
266 
267  /*!
268  * \brief gets all transisiton objects in this state
269  *
270  * \return vector with pointers to transition objects
271  */
272  ::std::vector< oETCS::DF::CTransition* > GetTransitions() const throw();
273 
274 
275 
276  /*!
277  * \brief gets the current data flow
278  *
279  * \return vector with pointers to all independent data flow objects
280  */
281  ::std::vector< CDataFlow* > GetCurrentDataFlow() const throw();
282 
283 
284 
285  /*!
286  * \brief register a new data flow object
287  *
288  * \param[in] ApplicationLevel literal name of the related application level
289  * \param[in] pDataFlow pointer to the data flow object to be registered
290  */
291  void AddDataFlow(const std::string& ApplicationLevel, CDataFlow * const pDataFlow) throw();
292 
293 
294 
295  /*!
296  * \brief register a new transition object
297  *
298  * \param[in] pTransition pointer to the transition object to be registered
299  */
300  void AddTransition(oETCS::DF::CTransition * const pTransition) throw();
301 
302 
303 
304 
305  private:
306  /*!
307  * \brief thread method/function for executing one data flow
308  *
309  * \param[in] iIndex index corresponding to the vector referenced by m_pCurrentDataFlow
310  */
311  void DataFlowThread(const unsigned int & iIndex) throw();
312 
313 
314 
315  /*!
316  * \brief flag for a state and/or level switch within the EVC state machine
317  */
319 
320 
321 
322  /*!
323  * \brief number of currently locked threads.
324  *
325  * Used in combination of m_Barrier to syncronise all data flow threads.
326  */
327  unsigned int m_iLockedThreads;
328 
329 
330 
331 
332  public:
333  /*!
334  * \brief pointer to the parent EVC state machine
335  */
337 
338 
339 
340 
341  private:
342  /*!
343  * \brief map of vectors of data flows in a certain EVC state indexed by the related application level
344  *
345  * Each vector holds a set of CDataFlow objects for a certain application level,
346  * which are independent from each other and therefore can be executed in parallel.
347  */
348  ::std::map< std::string, ::std::vector< CDataFlow* > > m_DataFlows;
349 
350 
351 
352  /*!
353  * \brief vector with pointers to all state transition within the current data flow
354  */
355  ::std::vector< oETCS::DF::CTransition* > m_Transitions;
356 
357 
358 
359  /*!
360  * \brief vector of pointers to the currently executed data flows
361  */
362  ::std::vector< CDataFlow* > m_CurrentDataFlow;
363 
364 
365 
366  /*!
367  * \brief condition variable as barrier for data flow syncronisation
368  */
369  ::std::condition_variable m_Barrier;
370 
371 
372 
373  /*!
374  * \brief vector of thread objects for data flow execution
375  */
376  ::std::vector< ::std::thread* > m_Threads;
377 
378 
379 
380  /*!
381  * \brief vector of exception thrown by data flow exections within threads
382  */
383  ::std::vector< ::oETCS::DF::Error::CException > m_DataFlowExceptions;
384 
385 
386 
387  /*!
388  * \brief vector with pointers to EVC transition objects, which were activated
389  */
390  ::std::vector< const oETCS::DF::CEVCTransition* > m_TransitionStack;
391 
392 
393 
394  friend class oETCS::DF::CEVCCondition;
395  friend class oETCS::DF::CLevelCondition;
396 
397  }; // class CEVCState
398 
399 
400 
401 
402  /*!
403  * \brief general constructor
404  */
405  CEVCStateMachine() throw();
406 
407 
408 
409  /*!
410  * \brief destructor
411  */
412  virtual ~CEVCStateMachine() throw();
413 
414 
415 
416  /*!
417  * \brief registers a function block object with thids state machine
418  *
419  * \param[in] pFunctionBlock pointer to function block object to be registered
420  *
421  */
422  void AddFunctionBlock(oETCS::DF::CFunctionBlock * const pFunctionBlock) throw();
423 
424 
425 
426  /*!
427  * \brief registers an EVC state object with thids state machine
428  *
429  * \param[in] pState pointer to EVC state object to be registered
430  *
431  */
432  void AddState(CEVCState * const pState) throw();
433 
434 
435 
436  /*!
437  * \brief registers an EVC transition object with thids state machine
438  *
439  * \param[in] pTransition pointer to EVC transition object to be registered
440  *
441  */
442  void AddTransition(oETCS::DF::CEVCTransition * const pTransition) throw();
443 
444 
445 
446  /*!
447  * \brief registers a language object with this state machine
448  *
449  * \param[in] pLanguage pointer to the language object to be registered
450  *
451  */
452  void AddLanguage(oETCS::DF::CLanguage * const pLanguage) throw();
453 
454 
455 
456  /*!
457  * \brief registers a flow object with this state machine
458  *
459  * \param[in] pFlow pointer to the flow object to be registered
460  *
461  */
462  void AddFlow(oETCS::DF::CAbstractFlow * const pFlow) throw();
463 
464 
465 
466  /*!
467  * \brief attaches a new DMI observer
468  *
469  * \param[in] pDMIObserver pointer to the observer
470  */
471  void AttachObserver(oETCS::DF::CDMIObserver * const pDMIObserver) throw();
472 
473 
474 
475  /*!
476  * \brief detaches a new DMI observer
477  *
478  * \param[in] pDMIObserver pointer to the observer
479  */
480  void DetachObserver(oETCS::DF::CDMIObserver * const pDMIObserver) throw();
481 
482 
483 
484  /*!
485  * \brief gets the pointer to the active EVC state
486  *
487  * \return pointer to active EVC state object
488  */
489  CEVCState* const GetActiveState() const throw();
490 
491 
492 
493  /*!
494  * \brief gets a vector with pointers to all EVC transitions
495  *
496  * \return vector with pointers to all EVC transition objects
497  */
498  ::std::vector< oETCS::DF::CEVCTransition* > GetTransitions() const throw();
499 
500 
501 
502  /*!
503  * \brief gets a vector with pointers to all EVC states
504  *
505  * \return vector with pointers to all EVC state objects
506  */
507  ::std::vector< CEVCState* > GetStates() const throw();
508 
509 
510 
511  /*!
512  * \brief gets a pointer to the current DMI subject
513  *
514  * \return pointer to the DMI subject
515  */
516  oETCS::DF::CDMISubject* GetCurrentDMI() throw();
517 
518 
519 
520  /*!
521  * \brief starts the execution of the EVC state machine
522  *
523  * Starts the the EVC state machine in a non-blocking manner.
524  *
525  * \param[in] pStartState pointer to EVC state object to start with (must be local vector)
526  * \param[in] ApplicationLevel literal name of the start application level (must be available in start state)
527  */
528  void Start(CEVCState * const pStartState, const std::string & ApplicationLevel) throw(::oETCS::DF::Error::CException);
529 
530 
531 
532  /*!
533  * \brief stops the execution of the EVC state machine
534  */
535  void Stop() throw(::oETCS::DF::Error::CException);
536 
537 
538 
539  /*!
540  * \brief notifies the state machine about a changed DMI subject
541  *
542  * Updates all registerd observers.
543  *
544  * \remark Should only be called by CDMIInput and CDMIOutput objects.
545  */
546  void Notify() throw();
547 
548 
549 
550 
551  private:
552  /*!
553  * \brief thread method/function for executing the current EVC state object
554  */
555  void StateThread() throw();
556 
557 
558 
559  /*!
560  * \brief flag for started EVC state machine
561  */
563 
564 
565 
566  /*!
567  * \brief vector with pointers all available EVC state objects
568  */
569  ::std::vector< CEVCState* > m_AvailableStates;
570 
571 
572 
573  /*!
574  * \brief vector with pointers to all transitions between EVC states
575  */
576  ::std::vector< oETCS::DF::CEVCTransition* > m_Transitions;
577 
578 
579 
580  /*!
581  * \brief vector of all CFunctionBlock objects used in the EVC state machine
582  */
583  ::std::vector< oETCS::DF::CFunctionBlock* > m_FunctionBlocks;
584 
585 
586 
587  /*!
588  * \brief literal name of the current active application level
589  */
591 
592 
593 
594  /*!
595  * \brief pointer to the active state
596  */
598 
599 
600 
601  /*!
602  * \brief pointer to thread object for EVC state object execution
603  */
604  ::std::thread* m_pThread;
605 
606 
607 
608  /*!
609  * \brief vector with pointers to all available language objects
610  */
611  ::std::vector< oETCS::DF::CLanguage* > m_Language;
612 
613 
614 
615  /*!
616  * \brief vector of pointers to registered observers
617  */
618  ::std::vector< oETCS::DF::CDMIObserver* > m_Observers;
619 
620 
621 
622  /*!
623  * \brief vector with all CFlow objects available in EVC state machine
624  */
625  ::std::vector< oETCS::DF::CAbstractFlow* > m_Flows;
626 
627 
628 
629  friend class oETCS::DF::CLevelCondition;
630 
631 // only include the following, if unit test framework is available
632 #ifdef __HAS_UNIT_TEST__
633 
635 
636 #endif // #ifdef __HAS_UNIT_TEST__
637 
638 }; // class CEVCStateMachine
639 
640 
641 
642 /*!
643  * \brief transition class for EVC states
644  */
646 {
647  public:
648  /*!
649  * \brief general constructor
650  *
651  * Parameterises the EVC state transition with all constant members.
652  *
653  * \param[in] pConditon pointer to the related condition object
654  * \param[in] pStartState pointer to the start EVC state object of the transtion
655  * \param[in] pTargetState pointer to the target EVC state object of the transtion
656  * \param[in] iPriority numerical priority of the transition
657  */
658  explicit CEVCTransition(oETCS::DF::CEVCCondition * const pCondition, oETCS::DF::CEVCStateMachine::CEVCState * const pStartState, oETCS::DF::CEVCStateMachine::CEVCState * const pTargetState, const unsigned int & iPriority = 0) throw();
659 
660 
661 
662  /*!
663  * \brief destructor
664  */
665  virtual ~CEVCTransition() throw();
666 
667 
668 
669  /*!
670  * \brief gets the pointer to the related EVC condition
671  *
672  * \return pointer to the related EVC condition object
673  */
674  const oETCS::DF::CEVCCondition* GetCondition() const throw();
675 
676 
677 
678  /*!
679  * \brief gets the pointer to the related EVC start state
680  *
681  * \return pointer to the related EVC start state object
682  */
683  oETCS::DF::CEVCStateMachine::CEVCState* const GetStartState() const throw();
684 
685 
686 
687  /*!
688  * \brief gets the pointer to the related EVC target state
689  *
690  * \return pointer to the related EVC target state object
691  */
692  oETCS::DF::CEVCStateMachine::CEVCState* const GetTargetState() const throw();
693 
694 
695 
696  /*!
697  * \brief gets the nurmerial priority
698  *
699  * \returns the numerical priority
700  */
701  unsigned int GetPriority() const throw();
702 
703 
704 
705 
706  private:
707  /*!
708  * \brief pointer to the related condition object
709  */
711 
712 
713 
714  /*!
715  * \brief pointer to the EVC start state object of the transition
716  */
718 
719 
720 
721  /*!
722  * \brief pointer to the target state of the transition
723  */
725 
726 
727 
728  /*!
729  * \brief numerical priority of a transition
730  */
731  const int m_iPriority;
732 
733 
734 
735 
736 }; // class CEVCTransition
737 
738 
739 
740 /*!
741  * \brief base class for all function block elements in a data flow
742  */
744 {
745  public:
746  /*!
747  * \brief container template class for input value storages of the type VALUE_T
748  *
749  * \tparam INPUT_TYPE_T: type of container value
750  */
751  template<class INPUT_TYPE_T>
752  class CInput
753  {
754  public:
755  /*!
756  * \brief default constructor
757  *
758  * Initialises m_Value by the default constructor of VALUE_T
759  */
760  explicit CInput() throw();
761 
762 
763 
764  /*!
765  * \brief general constructor
766  *
767  * \param[in] Value initial value of the container of template type
768  */
769  explicit CInput(const INPUT_TYPE_T& Value) throw();
770 
771 
772 
773  /*!
774  * \brief assigns a new value to the container
775  *
776  * \param[in] NewValue the new value
777  */
778  INPUT_TYPE_T& operator=(const INPUT_TYPE_T& NewValue) throw();
779 
780 
781 
782  /*!
783  * \brief gets the modified flag
784  *
785  * Returns true if the value mas modified by any operator/method.
786  * This methods reset the modified flag.
787  *
788  * \return modified flag
789  */
790  bool IsModified() throw();
791 
792 
793 
794  /*!
795  * \brief functor operator
796  *
797  * Returns the value.
798  *
799  * \return the value
800  */
801  INPUT_TYPE_T operator()() throw();
802 
803 
804 
805  /*!
806  * \brief functor operator
807  *
808  * Returns value.
809  *
810  * \remark This is the const version of the operator.
811  *
812  * \return value
813  */
814  const INPUT_TYPE_T operator()() const throw();
815 
816 
817 
818 
819  private:
820  /*!
821  * \brief real storage of the value type
822  */
823  INPUT_TYPE_T m_Value;
824 
825 
826 
827  /*!
828  * \brief modified flag for the container value
829  */
831 
832 
833 
834  /*!
835  * \brief mutex for I/O accesses to the value of the input
836  */
837  mutable ::std::mutex m_ValueMutex;
838 
839 
840 
841  friend class oETCS::DF::CStorage;
842 
843  }; // CInput
844 
845 
846 
847 
848  /*!
849  * \brief general constructor
850  *
851  * \param[in] pStateMachine pointer to the contenting state machine
852  */
853  CFunctionBlock(oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
854 
855 
856 
857  /*!
858  * \brief deleted copy constructor to avoid copying
859  */
860  CFunctionBlock(const CFunctionBlock& Source) = delete;
861 
862 
863 
864  /*!
865  * \brief destructor
866  */
867  virtual ~CFunctionBlock() throw();
868 
869 
870 
871  /*!
872  * \brief virtual method for computing all outputs and setting the all referenced outputs
873  *
874  * \remark must be implemented by any inheriting class
875  */
876  virtual void Calculate() throw(::oETCS::DF::Error::CException) = 0;
877 
878 
879 
880 
881  private:
882  /*!
883  * \brief private assignment operator to avoid assignment
884  */
885  CFunctionBlock& operator=(CFunctionBlock& Source) throw();
886 
887 
888 
889 
890  public:
891  /*!
892  * \brief pointer to the all contenting EVC state machine
893  */
895 
896 
897 
898 
899 }; // class CFunctionBlock
900 
901 template<class INPUT_TYPE_T>
902 CFunctionBlock::CInput<INPUT_TYPE_T>::CInput() throw()
903 :m_bModified(false)
904 {
905  // Bouml preserved body begin 0008E682
906  // empty constructor
907  // Bouml preserved body end 0008E682
908 
909 } // CFunctionBlock::CInput<INPUT_TYPE_T>::CInput() throw()
910 
911 
912 
913 
914 template<class INPUT_TYPE_T>
915 CFunctionBlock::CInput<INPUT_TYPE_T>::CInput(const INPUT_TYPE_T& Value) throw()
916 :m_Value(Value),
917  m_bModified(false)
918 {
919  // Bouml preserved body begin 00082A82
920  // empty constructor
921  // Bouml preserved body end 00082A82
922 
923 } // CFunctionBlock::CInput<INPUT_TYPE_T>::CInput() throw()
924 
925 
926 
927 
928 template<class INPUT_TYPE_T>
929 INPUT_TYPE_T& CFunctionBlock::CInput<INPUT_TYPE_T>::operator=(const INPUT_TYPE_T& NewValue) throw()
930 {
931  // Bouml preserved body begin 00082B82
932  // lock mutex
933  m_ValueMutex.lock();
934 
935  // set modified flag
936  m_bModified = true;
937 
938  // assign new value
939  m_Value = NewValue;
940 
941  // unlock mutex
942  m_ValueMutex.unlock();
943 
944  // return reference to local value
945  return (m_Value);
946  // Bouml preserved body end 00082B82
947 
948 } // INPUT_TYPE_T CFunctionBlock::CInput<INPUT_TYPE_T>::operator=() throw()
949 
950 
951 
952 
953 template<class INPUT_TYPE_T>
955 {
956  // Bouml preserved body begin 00082C02
957  bool bModified(m_bModified);
958 
959 
960 
961  // lock mutex
962  m_ValueMutex.lock();
963 
964  // reset modified flag
965  m_bModified = false;
966 
967  // unlock mutex
968  m_ValueMutex.unlock();
969 
970 
971  // return flag
972  return (bModified);
973  // Bouml preserved body end 00082C02
974 
975 } // bool CFunctionBlock::CInput<INPUT_TYPE_T>::IsModified() throw()
976 
977 
978 
979 
980 template<class INPUT_TYPE_T>
982 {
983  // Bouml preserved body begin 00082C82
984  INPUT_TYPE_T Value;
985 
986 
987 
988  // lock mutex
989  m_ValueMutex.lock();
990 
991  // get value from member
992  Value = m_Value;
993 
994  // unlock mutex
995  m_ValueMutex.unlock();
996 
997 
998  // return reference to local value
999  return (Value);
1000  // Bouml preserved body end 00082C82
1001 
1002 } // INPUT_TYPE_T CFunctionBlock::CInput<INPUT_TYPE_T>::operator()() throw()
1003 
1004 
1005 
1006 
1007 template<class INPUT_TYPE_T>
1008 const INPUT_TYPE_T CFunctionBlock::CInput<INPUT_TYPE_T>::operator()() const throw()
1009 {
1010  // Bouml preserved body begin 000AD602
1011  INPUT_TYPE_T Value;
1012 
1013 
1014 
1015  // lock mutex
1016  m_ValueMutex.lock();
1017 
1018  // get value from member
1019  Value = m_Value;
1020 
1021  // unlock mutex
1022  m_ValueMutex.unlock();
1023 
1024 
1025  // return reference to local value
1026  return (Value);
1027  // Bouml preserved body end 000AD602
1028 
1029 } // INPUT_TYPE_T CFunctionBlock::CInput<INPUT_TYPE_T>::operator()() const throw()
1030 
1031 
1032 
1033 
1034 
1035 
1036 /*!
1037  * \brief flow base class
1038  *
1039  * Used for addressing all template flows by one base pointer type.
1040  */
1042 {
1043  public:
1044  /*!
1045  * \brief general constructor
1046  *
1047  * \param[in] pStateMachine pointer to the parent state machine
1048  */
1049  CAbstractFlow(oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
1050 
1051 
1052 
1053  /*!
1054  * \brief destructor
1055  */
1056  virtual ~CAbstractFlow() throw();
1057 
1058 
1059 
1060 
1061  protected:
1062  /*!
1063  * \brief pointer to the all contenting EVC state machine
1064  */
1066 
1067 
1068 
1069 
1070 }; // class CAbstractFlow
1071 
1072 
1073 
1074 /*!
1075  * \brief flow template class
1076  *
1077  * Builds the connection of one input with one output for a certain data flow.
1078  *
1079  * \tparam INPUT_TYPE_T is the type of the input
1080  * \tparam FLOW_TYPE_T is the type of the data flow
1081  */
1082 template<class INPUT_TYPE_T, class FLOW_TYPE_T = ::oETCS::DF::CFunctionBlock::CInput< INPUT_TYPE_T > >
1084 {
1085  public:
1086  /*!
1087  * \brief general constructor
1088  *
1089  * \param[in] pInput pointer to the related input object
1090  * \param[in] pStateMachine pointer to the parent state machine
1091  */
1092  CFlow(FLOW_TYPE_T * const pInput, oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
1093 
1094 
1095 
1096  /*!
1097  * \brief assignment operator
1098  *
1099  * \param[in] Value concrete value of this data flow
1100  */
1101  void operator=(const INPUT_TYPE_T& Value) throw();
1102 
1103 
1104 
1105 
1106  private:
1107  /*!
1108  * \brief pointer to the related input of an function block object
1109  */
1110  FLOW_TYPE_T* const m_pInput;
1111 
1112 
1113 
1114 
1115 }; // class CFlow : public oETCS::DF::CAbstractFlow
1116 
1117 template<class INPUT_TYPE_T, class FLOW_TYPE_T>
1118 CFlow<INPUT_TYPE_T, FLOW_TYPE_T>::CFlow(FLOW_TYPE_T * const pInput, oETCS::DF::CEVCStateMachine * const pStateMachine) throw()
1119 :CAbstractFlow(pStateMachine),
1120  m_pInput(pInput)
1121 {
1122  // Bouml preserved body begin 000C5602
1123  // empty constructor
1124  // Bouml preserved body end 000C5602
1125 
1126 } // CFlow<INPUT_TYPE_T, FLOW_TYPE_T>::CFlow() throw()
1127 
1128 
1129 
1130 
1131 template<class INPUT_TYPE_T, class FLOW_TYPE_T>
1132 void CFlow<INPUT_TYPE_T, FLOW_TYPE_T>::operator=(const INPUT_TYPE_T& Value) throw()
1133 {
1134  // Bouml preserved body begin 000C5582
1135  // check, if this flow is part of the current data flow (active state nullptr means test case)
1136  if (m_pStateMachine->GetActiveState() == nullptr || m_pStateMachine->GetActiveState()->IsActiveFlow(this))
1137  {
1138  // set value in input value
1139  *m_pInput = Value;
1140 
1141 
1142 #ifdef __DEBUG_OUTPUT__
1143  // DEBUG
1144  ::std::cerr << std::this_thread::get_id() << " " << "CFlow::operator=() ----> value " << Value << " set in flow " << this << ::std::endl;
1145 #endif
1146 
1147 
1148  } // if (m_pStateMachine->GetActiveState() == nullptr || m_pStateMachine->GetActiveState()->IsActiveFlow(this))
1149 
1150  // Bouml preserved body end 000C5582
1151 
1152 } // void CFlow<INPUT_TYPE_T, FLOW_TYPE_T>::operator=() throw()
1153 
1154 
1155 
1156 
1157 
1158 
1159 /*!
1160  * \brief flow class for the meta model bit type
1161  *
1162  * Builds the connection/flow between to CStrorage objects
1163  *
1164  */
1166 {
1167  public:
1168  /*!
1169  * \brief general constructor
1170  *
1171  * \param[in] pInput pointer to the related CStorage object
1172  * \param[in] pStateMachine pointer to the parent state machine
1173  */
1174  explicit CBitFlow(oETCS::DF::CStorage * const pInput, oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
1175 
1176 
1177 
1178  /*!
1179  * \brief assignment operator
1180  *
1181  * \param[in] Value concrete value of this bit data flow
1182  */
1183  void operator=(const oETCS::DF::CStorage& Value) throw();
1184 
1185 
1186 
1187  /*!
1188  * \brief pointer access operator for connected input storage
1189  *
1190  * \return pointer to the underlying CStorage instance
1191  */
1192  oETCS::DF::CStorage* operator->() throw();
1193 
1194 
1195 
1196 
1197  private:
1198  /*!
1199  * \brief pointer to CStorage instance as bit input
1200  */
1202 
1203 
1204 
1205 
1206 }; // class CBitFlow : public oETCS::DF::CAbstractFlow
1207 
1208 
1209 
1210 /*!
1211  * \brief typedef for easier access in this namespace
1212  */
1214 
1215 
1216 /*!
1217  * \brief typedef for easier access in this namespace
1218  */
1220 
1221 
1222 /*!
1223  * \brief typedef for a boolean flow type
1224  */
1226 
1227 
1228 /*!
1229  * \brief typedef for a double array flow type
1230  */
1232 
1233 
1234 /*!
1235  * \brief typedef for a double flow type
1236  */
1238 
1239 
1240 /*!
1241  * \brief typedef for a integer flow type
1242  */
1244 
1245 
1246 /*!
1247  * \brief typedef for a string flow type
1248  */
1250 
1251 
1252 /*!
1253  * \brief typedef for a boolean container type
1254  */
1256 
1257 
1258 /*!
1259  * \brief typedef for the bool meta model input data type
1260  */
1262 
1263 
1264 /*!
1265  * \brief typedef for the bool meta model output data type
1266  */
1268 
1269 
1270 /*!
1271  * \brief typedef for a double array container type
1272  */
1274 
1275 
1276 /*!
1277  * \brief typedef for the double array meta model input data type
1278  */
1280 
1281 
1282 /*!
1283  * \brief typedef for the double array meta model output data type
1284  */
1286 
1287 
1288 /*!
1289  * \brief typedef for a double container type
1290  */
1292 
1293 
1294 /*!
1295  * \brief typedef for the double meta model input data type
1296  */
1298 
1299 
1300 /*!
1301  * \brief typedef for the double meta model output data type
1302  */
1304 
1305 
1306 /*!
1307  * \brief typedef for a integer container type
1308  */
1310 
1311 
1312 /*!
1313  * \brief typedef for the int meta model input data type
1314  */
1316 
1317 
1318 /*!
1319  * \brief typedef for the int meta model output data type
1320  */
1322 
1323 
1324 /*!
1325  * \brief typedef for a boolean container type
1326  */
1328 
1329 
1330 /*!
1331  * \brief typedef for the string meta model input data type
1332  */
1334 
1335 
1336 /*!
1337  * \brief typedef for the string meta model output data type
1338  */
1340 
1341 
1342 /*!
1343  * \brief typedef for the bit meta model output data type
1344  */
1346 
1347 
1348 /*!
1349  * \brief condition class for changing the current application level
1350  */
1352 {
1353  public:
1354  /*!
1355  * \brief general constructor
1356  *
1357  * \param[in] pStateMachine pointer to the parent EVC state machine object
1358  * \param[in] ApplicationLevel literal name of the application level for which the condition object is used
1359  */
1360  explicit CLevelCondition(oETCS::DF::CEVCStateMachine * const pStateMachine, const std::string & ApplicationLevel) throw();
1361 
1362 
1363 
1364  /*!
1365  * \brief destructor
1366  */
1367  virtual ~CLevelCondition() throw();
1368 
1369 
1370 
1371  /*!
1372  * \brief virtual method for computing all outputs and setting the all referenced outputs
1373  *
1374  * \remark must be implemented by any inheriting class
1375  */
1376  virtual void Calculate() throw(::oETCS::DF::Error::CException);
1377 
1378 
1379 
1380  /*!
1381  * \brief input storage for activating a application level switch by a condition object
1382  */
1384 
1385 
1386 
1387  /*!
1388  * \brief literal of the target application level of the condition
1389  */
1390  const ::std::string m_TargetApplicationLevel;
1391 
1392 
1393 
1394 
1395 }; // class CLevelCondition : public oETCS::DF::CFunctionBlock
1396 
1397 
1398 
1399 /*!
1400  * \brief condition/guard class for starting/transitioning (to) a certain EVC state
1401  */
1403 {
1404  public:
1405  /*!
1406  * \brief general constructor
1407  *
1408  * \param[in] pStateMachine pointer to the parent EVC state machine object
1409  */
1410  explicit CEVCCondition(oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
1411 
1412 
1413 
1414  /*!
1415  * \brief destructor
1416  */
1417  virtual ~CEVCCondition() throw();
1418 
1419 
1420 
1421  /*!
1422  * \brief virtual method for computing all outputs and setting the all referenced outputs
1423  *
1424  * \remark must be implemented by any inheriting class
1425  */
1426  virtual void Calculate() throw(::oETCS::DF::Error::CException);
1427 
1428 
1429 
1430  /*!
1431  * \brief input storage of the guard of the condition
1432  */
1434 
1435 
1436 
1437 
1438 }; // class CEVCCondition : public oETCS::DF::CFunctionBlock
1439 
1440 
1441 
1442 /*!
1443  * \brief subject of the DMI observer pattern
1444  *
1445  * Combines used DMI inputs and outputs for a certain data flow.
1446  */
1448 {
1449  /*!
1450  * \brief general constructor
1451  *
1452  * Parameterises the DMI widget with all constant members.
1453  * The Telegram object takes over the posession of the input and output elements.
1454  *
1455  * \param[in] Input vector with pointers to all DMI input objects used
1456  * \param[in] Outputs vector with pointers to all DMI output objects used
1457  */
1458  explicit CDMISubject(const ::std::vector< oETCS::DF::CDMIInput * >& Inputs, const ::std::vector< oETCS::DF::CDMIOutput * >& Outputs) throw();
1459 
1460 
1461 
1462  /*!
1463  * \brief destructor
1464  */
1465  virtual ~CDMISubject() throw();
1466 
1467 
1468 
1469  /*!
1470  * \brief vector of pointers to input elements
1471  */
1472  ::std::vector< oETCS::DF::CDMIInput* > m_Inputs;
1473 
1474 
1475 
1476  /*!
1477  * \brief vector of pointers to outputs
1478  */
1479  ::std::vector< oETCS::DF::CDMIOutput* > m_Outputs;
1480 
1481 
1482 
1483 
1484 }; // struct CDMISubject
1485 
1486 
1487 
1488 /*!
1489  * \brief observer interface for the DMI
1490  *
1491  * Must be reimplemented by any concrete observer.
1492  */
1494 {
1495  public:
1496  /*!
1497  * \brief general constructor
1498  *
1499  * Attaches the concrete obsever to the EVC state machine.
1500  *
1501  * \param[in] pStateMachine pointer to the related state machine
1502  */
1503  CDMIObserver(oETCS::DF::CEVCStateMachine * const pStateMachine) throw();
1504 
1505 
1506 
1507  /*!
1508  * \brief updates the observer representation
1509  */
1510  virtual void Update() throw() = 0;
1511 
1512 
1513 
1514  /*!
1515  * \brief notifies an observer about it was detached by the EVC state machine
1516  */
1517  virtual void Detached() throw() = 0;
1518 
1519 
1520 
1521 
1522  protected:
1523  /*!
1524  * \brief pointer to the related state machine
1525  */
1527 
1528 
1529 
1530 
1531 }; // class CDMIObserver
1532 
1533 
1534 
1535 /*!
1536  * \brief helper method for streaming a double vector
1537  *
1538  * \param[in] OutStream stream object used for output
1539  * \param[in] Vector output vector of double
1540  *
1541  * \return reference to the outstream
1542  */
1543 ::std::ostream& operator<<(::std::ostream & OutStream, const ::std::vector< double >& Vector) throw();
1544 
1545 
1546 
1547 
1548 } // namespace oETCS::DF
1549 
1550 } // namespace oETCS
1551 
1552 #endif // __ OETCS_DF_EVCSTATEMACHINE_H__

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/.