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 
26 
27 #include "StatechartManager.h"
28 
29 #include "StateController.h"
30 #include "State.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 StatechartManager::setToplevelState(const StatePtr& newToplevelState, StringVariantContainerBaseMap startParameters)
48 {
49  if (isRunning())
50  {
51  return false;
52  }
53 
54  toplevelState = newToplevelState;
55  this->startParameters = startParameters;
56  return true;
57 }
58 
60 {
61  return toplevelState;
62 }
63 
64 void StatechartManager::start(bool enterToplevelState)
65 {
66  ARMARX_DEBUG << "starting StatechartManager";
67  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
68  // HiddenTimedMutex::scoped_lock lock(runningTaskMutex);
69 
70 
71  if (!runningTask && managerState != eShutDown)
72  {
73  if (toplevelState)
74  {
75  ARMARX_DEBUG << "starting StatechartManagerTask";
76 
77  runningTask = new RunningTask<StatechartManager>(this, &StatechartManager::processEvents, "StatechartManager");
78  runningTask->start();
79  managerState = eRunning;
80  lock.unlock();
81 
82  if (enterToplevelState)
83  {
84  toplevelState->enter(startParameters);
85  }
86 
87  // toplevelState = NULL;
88  }
89  else
90  {
91  throw LocalException("No toplevel state was set in StatechartManager!");
92  }
93 
94  }
95 }
96 
97 void
99 {
100  if (isShutdown())
101  {
102  return;
103  }
104 
105  {
106  // HiddenTimedMutex::scoped_lock lock(runningTaskMutex);
107  HiddenTimedMutex::ScopedLock lock2(managerStateMutex);
108  managerState = eShutDown;
109  }
110 
111  // ARMARX_INFO << "RefCount: " << toplevelState->IceUtil::Shared::__getRef();
112  if (toplevelState)
113  {
114  toplevelState->disableRunFunction();
115  }
116 
117  toplevelState = nullptr; // delete so that there are not ring pointers
118 
119 
120  // first issue stop, then wake up, then wait
121  {
122  std::unique_lock lock(eventQueueMutex); // necessary?
123 
124  if (runningTask)
125  {
126  runningTask->stop(false);
127  }
128 
129  idleCondition.notify_one();
130  }
131 
132  if (runningTask)
133  {
134  runningTask->waitForFinished();
135  }
136 
137 
138  ARMARX_VERBOSE << "StatechartManager is shutdown!";
139 }
140 
142 {
143  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
144 
145  if (managerState == eRunning)
146  {
147  return true;
148  }
149 
150  return false;
151 }
152 
154 {
155  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
156 
157  if (managerState == eShutDown)
158  {
159  return true;
160  }
161 
162  return false;
163 }
164 
166 {
167  HiddenTimedMutex::ScopedLock lock(managerStateMutex);
168  return managerState;
169 }
170 
172 {
173  idleCondition.notify_all();
174 }
175 
176 bool StatechartManager::addEvent(const EventPtr& newEvent, const StateControllerPtr& receivingState)
177 {
178  // HiddenTimedMutex::scoped_lock lock2(runningTaskMutex);
179  {
180  HiddenTimedMutex::ScopedLock lock2(managerStateMutex);
181 
182  if (!runningTask || !runningTask->isRunning())
183  {
184  return false;
185  }
186 
187  if (!newEvent || !receivingState)
188  {
189  return false;
190  }
191 
192  }
193  EventProcessingData data;
194  data.event = newEvent;
195  data.receivingState = receivingState;
196  /* if(!checkEvent(data))
197  {
198  ARMARX_INFO << "event skipped: " << newEvent->eventName;
199  // return true;
200  }*/
201 
202  std::unique_lock lock(eventQueueMutex);
203  eventQueue.push_back(data);
204  // ARMARX_INFO << "New event: " << newEvent->eventName << " for " << receivingState->getStateName();
205  idleCondition.notify_one();
206  return true;
207 }
208 
209 void
211 {
212 
213  while (!runningTask->isStopped())
214  {
215  EventProcessingData nextEvent;
216  {
217  // just retrieve the event and release the lock
218  std::unique_lock lock(eventQueueMutex);
219 
220  if (eventQueue.size() > 0)
221  {
222  nextEvent = eventQueue.front();
223  eventQueue.pop_front();
224  }
225  }
226 
227  try
228  {
229  if (nextEvent.receivingState)
230  {
232  {
233  TimeUtil::WaitForNextTick(); // delay transition if time is not running
234  }
235  nextEvent.receivingState->__processEvent(nextEvent.event);
236  }
237  }
238  catch (...)
239  {
241  }
242 
243  std::unique_lock lock(eventQueueMutex); // lock so that no events can be added
244 
245  // between size checking and going to sleep AND that shutdown cannot be issued after isStopped() was checked
246  if (runningTask->isStopped())
247  {
248  break;
249  }
250 
251  while (eventQueue.size() == 0 && !runningTask->isStopped())
252  {
253  // wait in idle mode until new events are available
254  // ARMARX_VERBOSE << "Waiting...";
255  idleCondition.wait(lock);
256  }
257  }
258 }
259 
260 bool StatechartManager::checkEvent(const StatechartManager::EventProcessingData& eventData) const
261 {
262  std::unique_lock lock(eventQueueMutex);
263  std::list<EventProcessingData>::const_iterator it = eventQueue.begin();
264 
265  for (; it != eventQueue.end(); it++)
266  {
267  if (eventData.receivingState == it->receivingState)
268  {
269  return false;
270  }
271  }
272 
273  return true;
274 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::StatechartManager::processEvents
virtual void processEvents()
Definition: StatechartManager.cpp:210
armarx::StatechartManager::getToplevelState
StatePtr getToplevelState() const
Definition: StatechartManager.cpp:59
armarx::StatechartManager::eShutDown
@ eShutDown
Definition: StatechartManager.h:69
armarx::StatechartManager::getManagerState
StatechartManagerState getManagerState() const
Definition: StatechartManager.cpp:165
armarx::StatechartManager::eRunning
@ eRunning
Definition: StatechartManager.h:68
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:35
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:171
armarx::StatechartManager::StatechartManager
StatechartManager()
Definition: StatechartManager.cpp:34
IceInternal::Handle< State >
StateController.h
armarx::StatechartManager::StatechartManagerState
StatechartManagerState
Definition: StatechartManager.h:65
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:114
State.h
armarx::StatechartManager::isShutdown
bool isShutdown() const
Definition: StatechartManager.cpp:153
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::StatechartManager::shutdown
void shutdown()
Definition: StatechartManager.cpp:98
armarx::TimeUtil::WaitForNextTick
static void WaitForNextTick()
block until the next tick of the timeserver.
Definition: TimeUtil.cpp:104
armarx::StatechartManager::start
void start(bool enterToplevelState=true)
Definition: StatechartManager.cpp:64
armarx::StatechartManager::addEvent
bool addEvent(const EventPtr &newEvent, const StateControllerPtr &receivingState)
Definition: StatechartManager.cpp:176
StatechartManager.h
TimeUtil.h
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:55
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:141
armarx::HiddenTimedMutex::ScopedLock
boost::unique_lock< HiddenTimedMutex > ScopedLock
Definition: Synchronization.h:122
armarx::StatechartManager::setToplevelState
bool setToplevelState(const armarx::StatePtr &newToplevelState, StringVariantContainerBaseMap startParameters=StringVariantContainerBaseMap())
setToplevelState sets the toplevel state of this manager.
Definition: StatechartManager.cpp:47
armarx::StatechartManager::isRunning
bool isRunning() const
Definition: StatechartManager.cpp:141
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28