openETCS
case study for the European Train Control System developed for the authors dissertation
ControlFlow.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 control flow classes
23  */
24 
25 #include "ControlFlow.h"
26 #include "Transition.h"
27 
28 
29 
30 
31 namespace oETCS {
32 
33 namespace DF {
34 
35 
36 CControlFlow::CState::CState(oETCS::DF::CControlFlow * const pParent, const std::string & StateName, const ::std::vector< oETCS::DF::CFunctionBlock * >& FunctionBlocks, const ::std::vector< oETCS::DF::CAbstractFlow * >& Flows, const bool & bIsFinal, const bool & bIsInitial) throw()
37 :m_Name(StateName),
38  m_bIsFinal(bIsFinal),
39  m_pParent(pParent),
40  m_TransitionStack(0),
41  m_FunctionBlocks(FunctionBlocks),
42  m_Flows(Flows)
43 {
44  // Bouml preserved body begin 00068882
45  // check, if parent pointer is valid
46  if (pParent != 0)
47  {
48  // register this instance at parent control flow
49  pParent->AddState(this, bIsInitial);
50 
51  } // if (pParent != 0)
52  // Bouml preserved body end 00068882
53 
54 } // CControlFlow::CState::CState() throw()
55 
56 
57 
58 
60 {
61  // Bouml preserved body begin 00068902
62  // empty constructor
63  // Bouml preserved body end 00068902
64 
65 } // CControlFlow::CState::~CState() throw()
66 
67 
68 
69 
70 bool CControlFlow::CState::IsActiveFunctionBlock(const oETCS::DF::CFunctionBlock * const pFunctionBlock) const throw()
71 {
72  // Bouml preserved body begin 00093782
73  bool bFound(false);
74  unsigned int x(0);
75  const unsigned int NUMBER_FUNCTION_BLOCKS(m_FunctionBlocks.size());
76 
77 
78 
79  // process all function block objects
80  for (x = 0; x < NUMBER_FUNCTION_BLOCKS && !bFound; x++)
81  {
82  // check current function block object for identity
83  bFound = (m_FunctionBlocks[x] == pFunctionBlock);
84 
85  // check, if not is identical, if current is a (nested) control flow
86  if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x]) != 0)
87  {
88  // call method recursively on control flow
89  bFound = dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x])->IsActiveFunctionBlock(pFunctionBlock);
90 
91  } // if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(m_FunctionBlocks[x]) != 0)
92 
93  } // for (x = 0; x < NUMBER_FUNCTION_BLOCKS && !bFound; x++)
94 
95  // return found flag
96  return bFound;
97  // Bouml preserved body end 00093782
98 
99 } // bool CControlFlow::CState::IsActiveFunctionBlock() const throw()
100 
101 
102 
103 
104 bool CControlFlow::CState::IsActiveFlow(const oETCS::DF::CAbstractFlow * const pFlow) const throw()
105 {
106  // Bouml preserved body begin 000CA382
107  bool bFound(false);
108  decltype (m_Flows.begin()) f;
109  decltype (m_FunctionBlocks.begin()) fb;
110 
111 
112 
113  // process all flow object
114  for (f = m_Flows.begin(); f != m_Flows.end() && not bFound; f++)
115  {
116  // check current function block object for identity
117  bFound = (*f == pFlow);
118 
119  } // for (f = m_Flows.begin(); f != m_Flows.end() && not bFound; f++)
120 
121  // check all control flow objects
122  for (fb = m_FunctionBlocks.begin(); fb != m_FunctionBlocks.end() && not bFound; fb++)
123  {
124  // check, if current is a control flow
125  if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(*fb) != 0)
126  {
127  // call method recursively on control flow
128  bFound = dynamic_cast< ::oETCS::DF::CControlFlow* >(*fb)->IsActiveFlow(pFlow);
129 
130  } // if (!bFound && dynamic_cast< ::oETCS::DF::CControlFlow* >(*fb) != 0)
131 
132  } // for (fb = m_FunctionBlocks.begin(); fb != m_FunctionBlocks.end() && not bFound; fb++)
133 
134  // return found flag
135  return bFound;
136  // Bouml preserved body end 000CA382
137 
138 } // bool CControlFlow::CState::IsActiveFlow() const throw()
139 
140 
141 
142 
143 void CControlFlow::CState::Execute() throw(::oETCS::DF::Error::CException)
144 {
145  // Bouml preserved body begin 00074D02
146  unsigned int x(0);
147  const unsigned int NUMBER_FUNCTION_BLOCKS(m_FunctionBlocks.size());
148  ::oETCS::DF::CTransition* pTransition(0);
149 
150 
151 
152 
153 #ifdef __DEBUG_OUTPUT__
154  // DEBUG
155  ::std::cerr << std::this_thread::get_id() << " " << "CState::Execute()() ----> method entered of state " << this->m_Name << ::std::endl;
156 #endif
157  try
158  {
159  // execute all related function block objects
160  for (x = 0; x < NUMBER_FUNCTION_BLOCKS; x++)
161  {
162 #ifdef __DEBUG_OUTPUT__
163  // DEBUG
164  ::std::cerr << std::this_thread::get_id() << " " << "CState::Execute()() ----> about to execute function block " << x << ::std::endl;
165 #endif
166 
167  // calculate current function block
168  m_FunctionBlocks[x]->Calculate();
169 
170  } // for (x = 0; x < NUMBER_FUNCTION_BLOCKS; x++)
171 
172 
173  // check, if transition stack is not empty
174  if (!m_TransitionStack.empty())
175  {
176  // store first transition on stack
177  pTransition = m_TransitionStack[0];
178 
179  // find transition with highest priority
180  for (x = 0; x < m_TransitionStack.size(); x++)
181  {
182  // compare priorities
183  if (pTransition->GetPriority() < m_TransitionStack[x]->GetPriority())
184  {
185  // store current transition
186  pTransition = m_TransitionStack[x];
187 
188  } // if (pTransition->GetPriority() < m_TransitionStack[x]->GetPriority())
189 
190  } // for (x = 0; x < m_TransitionStack.size(); x++)
191 
192  // execute transition
193  m_pParent->m_pCurrentState = pTransition->GetTargetState();
194 
195 #ifdef __DEBUG_OUTPUT__
196  // DEBUG
197  ::std::cerr << std::this_thread::get_id() << " " << "CState::Execute()() ----> executed transition to new state " << m_pParent->m_pCurrentState << ::std::endl;
198 #endif
199 
200  } // if (!m_TransitionStack.empty())
201 
202  // check, if this state is a final state
203  if (m_bIsFinal)
204  {
205  // tell parent control flow to terminate
206  m_pParent->m_pCurrentState = 0;
207 
208 #ifdef __DEBUG_OUTPUT__
209  // DEBUG
210  ::std::cerr << std::this_thread::get_id() << " " << "CState::Execute()() ----> final state reached" << ::std::endl;
211 #endif
212 
213  } // if (m_bIsFinal)
214 
215  } // try
216  catch (const ::oETCS::DF::Error::CException&)
217  {
218  // re-throw exception
219  throw;
220 
221  } // catch (const ::oETCS::DF::Error::CException&)
222  // Bouml preserved body end 00074D02
223 
224 } // void CControlFlow::CState::Execute() throw(::oETCS::DF::Error::CException)
225 
226 
227 
228 
230 :CFunctionBlock(pStateMachine),
231  m_bStart(false),
232  m_pCurrentState(0),
233  m_pInitialState(0)
234 {
235  // Bouml preserved body begin 00063182
236  // empty constructor
237  // Bouml preserved body end 00063182
238 
239 } // CControlFlow::CControlFlow() throw()
240 
241 
242 
243 
245 {
246  // Bouml preserved body begin 00063202
247  unsigned int x(0);
248 
249 
250  // delete all states
251  for (x = 0; x < m_AvailableStates.size(); x++)
252  {
253  // delete current telegram
254  delete m_AvailableStates[x];
255 
256  } // for (x = 0; x < m_AvailableStates.size(); x++)
257  // Bouml preserved body end 00063202
258 
259 } // CControlFlow::~CControlFlow() throw()
260 
261 
262 
263 
264 void CControlFlow::AddState(oETCS::DF::CControlFlow::CState * const pState, const bool& bIsInitial) throw()
265 {
266  // Bouml preserved body begin 00091D82
267  // check, if state pointer is valid
268  if (pState != 0)
269  {
270  // add state object to vector
271  m_AvailableStates.push_back(pState);
272 
273  // check, if state is initial state
274  if (bIsInitial)
275  {
276  // set state object as initial state object
277  m_pInitialState = pState;
278 
279  } // if (bIsInitial)
280 
281  } // if (pState != 0)
282  // Bouml preserved body end 00091D82
283 
284 } // void CControlFlow::AddState() throw()
285 
286 
287 
288 
289 bool CControlFlow::IsActiveFunctionBlock(const oETCS::DF::CFunctionBlock * const pFunctionBlock) const throw()
290 {
291  // Bouml preserved body begin 00093702
292  bool bFound(false);
293 
294 
295  // check, if control flow is running
296  if (m_pCurrentState != 0)
297  {
298  // get result form active state
299  bFound = m_pCurrentState->IsActiveFunctionBlock(pFunctionBlock);
300 
301  } // if (m_pCurrentState != 0)
302 
303  // return found value
304  return bFound;
305  // Bouml preserved body end 00093702
306 
307 } // bool CControlFlow::IsActiveFunctionBlock() const throw()
308 
309 
310 
311 
312 bool CControlFlow::IsActiveFlow(const oETCS::DF::CAbstractFlow * const pFlow) const throw()
313 {
314  // Bouml preserved body begin 000CA402
315  bool bFound(false);
316 
317 
318  // check, if control flow is running
319  if (m_pCurrentState != 0)
320  {
321  // get result form active state
322  bFound = m_pCurrentState->IsActiveFlow(pFlow);
323 
324  } // if (m_pCurrentState != 0)
325 
326  // return found value
327  return bFound;
328  // Bouml preserved body end 000CA402
329 
330 } // bool CControlFlow::IsActiveFlow() const throw()
331 
332 
333 
334 
336 {
337  // Bouml preserved body begin 00086102
338  // return pointer to current state
339  return m_pCurrentState;
340  // Bouml preserved body end 00086102
341 
342 } // oETCS::DF::CControlFlow::CState CControlFlow::GetCurrentState() const throw()
343 
344 
345 
346 
347 void CControlFlow::Calculate() throw(::oETCS::DF::Error::CException)
348 {
349  // Bouml preserved body begin 00063102
350  unsigned int x(0);
351  const unsigned int NUMBER_RUNNING_OUTPUTS(m_IsRunning.size());
352  const unsigned int NUMBER_STATE_OUTPUTS(m_ActiveStateName.size());
353 
354 
355 
356 #ifdef __DEBUG_OUTPUT__
357  // DEBUG
358  ::std::cerr << std::this_thread::get_id() << " " << "CControlFlow::Calculate() ----> method entered " << ::std::endl;
359 #endif
360 
361  // check, if control flow is started and was not running
362  if (m_pCurrentState == 0 && m_pInitialState != 0 && m_bStart())
363  {
364  // assign initial state object as current one
366 
367 #ifdef __DEBUG_OUTPUT__
368  // DEBUG
369  ::std::cerr << std::this_thread::get_id() << " " << "CControlFlow::Calculate() ----> (re)started control flow with initial state " << m_pCurrentState << ::std::endl;
370 #endif
371 
372  } // if (m_pCurrentState == 0 && m_pInitialState != 0 && m_bStart())
373 
374  // check, if a current state is available
375  if (m_pCurrentState != 0)
376  {
377 #ifdef __DEBUG_OUTPUT__
378  // DEBUG
379  ::std::cerr << std::this_thread::get_id() << " " << "CControlFlow::Calculate() ----> about to execute current state " << m_pCurrentState << ::std::endl;
380 #endif
381 
382  for (x = 0; x < NUMBER_STATE_OUTPUTS; x++)
383  {
384  // set current output
386 
387  } // for (x = 0; x < NUMBER_STATE_OUTPUTS; x++)
388 
389  try
390  {
391  // execute current active state
393 
394  } // try
395  catch (const ::oETCS::DF::Error::CException&)
396  {
397  // re-throw exception
398  throw;
399 
400  } // catch (const ::oETCS::DF::Error::CException&)
401 
402  } // if (m_pCurrentState != 0)
403 
404  // set running flag in all outputs
405  for (x = 0; x < NUMBER_RUNNING_OUTPUTS; x++)
406  {
407  // set current output
408  *(m_IsRunning[x]) = (m_pCurrentState != 0);
409 
410  } // for (x = 0; x < NUMBER_RUNNING_OUTPUTS; x++)
411 
412  // Bouml preserved body end 00063102
413 
414 } // void CControlFlow::Calculate() throw(::oETCS::DF::Error::CException)
415 
416 
417 
418 
419 
420 
421 } // namespace oETCS::DF
422 
423 } // 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/.