StatechartManager.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarX::Core::Statechart
19 * @author Mirko Waechter ( mirko.waechter at kit dot edu)
20 * @date 2012
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24 
25 #include "StatechartManager.h"
26 
28 
29 #include "State.h"
30 #include "StateController.h"
31 
32 using namespace armarx;
33 
35  managerState(eConstructed),
36  // runningTaskMutex(10000, "runningTaskMutex")
37  managerStateMutex(10000, "managerStateMutex")
38 {
39  setTag("StatechartManager");
40 }
41 
43 {
44  shutdown();
45 }
46 
47 bool
49  StringVariantContainerBaseMap startParameters)
50 {
51  if (isRunning())
52  {
53  return false;
54  }
55 
56  toplevelState = newToplevelState;
57  this->startParameters = startParameters;
58  return true;
59 }
60 
63 {
64  return toplevelState;
65 }
66 
67 void
68 StatechartManager::start(bool enterToplevelState)
69 {
70  ARMARX_DEBUG << "starting StatechartManager";
71  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
72  // HiddenTimedMutex::scoped_lock lock(runningTaskMutex);
73 
74 
75  if (!runningTask && managerState != eShutDown)
76  {
77  if (toplevelState)
78  {
79  ARMARX_DEBUG << "starting StatechartManagerTask";
80 
81  runningTask = new RunningTask<StatechartManager>(
82  this, &StatechartManager::processEvents, "StatechartManager");
83  runningTask->start();
84  managerState = eRunning;
85  lock.unlock();
86 
87  if (enterToplevelState)
88  {
89  toplevelState->enter(startParameters);
90  }
91 
92  // toplevelState = NULL;
93  }
94  else
95  {
96  throw LocalException("No toplevel state was set in StatechartManager!");
97  }
98  }
99 }
100 
101 void
103 {
104  if (isShutdown())
105  {
106  return;
107  }
108 
109  {
110  // HiddenTimedMutex::scoped_lock lock(runningTaskMutex);
111  HiddenTimedMutex::ScopedLock lock2(managerStateMutex);
112  managerState = eShutDown;
113  }
114 
115  // ARMARX_INFO << "RefCount: " << toplevelState->IceUtil::Shared::__getRef();
116  if (toplevelState)
117  {
118  toplevelState->disableRunFunction();
119  }
120 
121  toplevelState = nullptr; // delete so that there are not ring pointers
122 
123 
124  // first issue stop, then wake up, then wait
125  {
126  std::unique_lock lock(eventQueueMutex); // necessary?
127 
128  if (runningTask)
129  {
130  runningTask->stop(false);
131  }
132 
133  idleCondition.notify_one();
134  }
135 
136  if (runningTask)
137  {
138  runningTask->waitForFinished();
139  }
140 
141 
142  ARMARX_VERBOSE << "StatechartManager is shutdown!";
143 }
144 
145 bool
147 {
148  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
149 
150  if (managerState == eRunning)
151  {
152  return true;
153  }
154 
155  return false;
156 }
157 
158 bool
160 {
161  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
162 
163  if (managerState == eShutDown)
164  {
165  return true;
166  }
167 
168  return false;
169 }
170 
173 {
174  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
175  return managerState;
176 }
177 
178 void
180 {
181  idleCondition.notify_all();
182 }
183 
184 bool
185 StatechartManager::addEvent(const EventPtr& newEvent, const StateControllerPtr& receivingState)
186 {
187  // HiddenTimedMutex::scoped_lock lock2(runningTaskMutex);
188  {
189  HiddenTimedMutex::ScopedLock lock2(managerStateMutex);
190 
191  if (!runningTask || !runningTask->isRunning())
192  {
193  return false;
194  }
195 
196  if (!newEvent || !receivingState)
197  {
198  return false;
199  }
200  }
201  EventProcessingData data;
202  data.event = newEvent;
203  data.receivingState = receivingState;
204  /* if(!checkEvent(data))
205  {
206  ARMARX_INFO << "event skipped: " << newEvent->eventName;
207  // return true;
208  }*/
209 
210  std::unique_lock lock(eventQueueMutex);
211  eventQueue.push_back(data);
212  // ARMARX_INFO << "New event: " << newEvent->eventName << " for " << receivingState->getStateName();
213  idleCondition.notify_one();
214  return true;
215 }
216 
217 void
219 {
220 
221  while (!runningTask->isStopped())
222  {
223  EventProcessingData nextEvent;
224  {
225  // just retrieve the event and release the lock
226  std::unique_lock lock(eventQueueMutex);
227 
228  if (eventQueue.size() > 0)
229  {
230  nextEvent = eventQueue.front();
231  eventQueue.pop_front();
232  }
233  }
234 
235  try
236  {
237  if (nextEvent.receivingState)
238  {
240  {
241  TimeUtil::WaitForNextTick(); // delay transition if time is not running
242  }
243  nextEvent.receivingState->__processEvent(nextEvent.event);
244  }
245  }
246  catch (...)
247  {
249  }
250 
251  std::unique_lock lock(eventQueueMutex); // lock so that no events can be added
252 
253  // between size checking and going to sleep AND that shutdown cannot be issued after isStopped() was checked
254  if (runningTask->isStopped())
255  {
256  break;
257  }
258 
259  while (eventQueue.size() == 0 && !runningTask->isStopped())
260  {
261  // wait in idle mode until new events are available
262  // ARMARX_VERBOSE << "Waiting...";
263  idleCondition.wait(lock);
264  }
265  }
266 }
267 
268 bool
269 StatechartManager::checkEvent(const StatechartManager::EventProcessingData& eventData) const
270 {
271  std::unique_lock lock(eventQueueMutex);
272  std::list<EventProcessingData>::const_iterator it = eventQueue.begin();
273 
274  for (; it != eventQueue.end(); it++)
275  {
276  if (eventData.receivingState == it->receivingState)
277  {
278  return false;
279  }
280  }
281 
282  return true;
283 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::StatechartManager::processEvents
virtual void processEvents()
Definition: StatechartManager.cpp:218
armarx::StatechartManager::getToplevelState
StatePtr getToplevelState() const
Definition: StatechartManager.cpp:62
armarx::StatechartManager::eShutDown
@ eShutDown
Definition: StatechartManager.h:67
armarx::StatechartManager::getManagerState
StatechartManagerState getManagerState() const
Definition: StatechartManager.cpp:172
armarx::StatechartManager::eRunning
@ eRunning
Definition: StatechartManager.h:66
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:36
armarx::StatechartManager::wakeUp
void wakeUp()
wakeUp signals the event processing thread to wake up and check for new events or shutdown conditions
Definition: StatechartManager.cpp:179
armarx::StatechartManager::StatechartManager
StatechartManager()
Definition: StatechartManager.cpp:34
IceInternal::Handle< State >
StateController.h
armarx::StatechartManager::StatechartManagerState
StatechartManagerState
Definition: StatechartManager.h:63
armarx::StatechartManager::~StatechartManager
~StatechartManager() override
Definition: StatechartManager.cpp:42
armarx::TimeUtil::HasTimeServer
static bool HasTimeServer()
check if we have been initialized with a Timeserver
Definition: TimeUtil.cpp:124
State.h
armarx::StatechartManager::isShutdown
bool isShutdown() const
Definition: StatechartManager.cpp:159
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::StatechartManager::shutdown
void shutdown()
Definition: StatechartManager.cpp:102
armarx::TimeUtil::WaitForNextTick
static void WaitForNextTick()
block until the next tick of the timeserver.
Definition: TimeUtil.cpp:112
armarx::StatechartManager::start
void start(bool enterToplevelState=true)
Definition: StatechartManager.cpp:68
armarx::StatechartManager::addEvent
bool addEvent(const EventPtr &newEvent, const StateControllerPtr &receivingState)
Definition: StatechartManager.cpp:185
StatechartManager.h
TimeUtil.h
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:54
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
armarx::HiddenTimedMutex::ScopedLock
boost::unique_lock< HiddenTimedMutex > ScopedLock
Definition: Synchronization.h:139
armarx::StatechartManager::setToplevelState
bool setToplevelState(const armarx::StatePtr &newToplevelState, StringVariantContainerBaseMap startParameters=StringVariantContainerBaseMap())
setToplevelState sets the toplevel state of this manager.
Definition: StatechartManager.cpp:48
armarx::StatechartManager::isRunning
bool isRunning() const
Definition: StatechartManager.cpp:146
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27