SMACC
Loading...
Searching...
No Matches
smacc_state_machine_impl.h
Go to the documentation of this file.
1/*****************************************************************************************************************
2 * ReelRobotix Inc. - Software License Agreement Copyright (c) 2018
3 * Authors: Pablo Inigo Blasco, Brett Aldrich
4 *
5 ******************************************************************************************************************/
6
7#pragma once
8
10
11#include <smacc/smacc_client.h>
13#include <smacc/smacc_state.h>
14
18#include <smacc_msgs/SmaccStatus.h>
19#include <sstream>
20
21#include <boost/function_types/function_arity.hpp>
22#include <boost/function_types/function_type.hpp>
23#include <boost/function_types/parameter_types.hpp>
24
25namespace smacc
26{
27 using namespace smacc::introspection;
28
29 template <typename TOrthogonal>
31 {
32 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
33
34 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
35 TOrthogonal *ret;
36
37 auto it = orthogonals_.find(orthogonalkey);
38
39 if (it != orthogonals_.end())
40 {
41 ROS_DEBUG("Orthogonal %s resource is being required from some state, client or component. Found resource in cache.", orthogonalkey.c_str());
42 ret = dynamic_cast<TOrthogonal *>(it->second.get());
43 return ret;
44 }
45 else
46 {
47 std::stringstream ss;
48 ss << "Orthogonal not found " << orthogonalkey.c_str() << std::endl;
49 ss << "The existing orthogonals are the following: " << std::endl;
50 for (auto &orthogonal : orthogonals_)
51 {
52 ss << " - " << orthogonal.first << std::endl;
53 }
54
55 ROS_WARN_STREAM(ss.str());
56
57 return nullptr;
58 }
59 }
60
61 //-------------------------------------------------------------------------------------------------------
62 template <typename TOrthogonal>
64 {
65 this->lockStateMachine("create orthogonal");
66 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
67
68 if (orthogonals_.count(orthogonalkey) == 0)
69 {
70 auto ret = std::make_shared<TOrthogonal>();
71 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc::ISmaccOrthogonal>(ret);
72
73 ret->setStateMachine(this);
74
75 ROS_INFO("%s Orthogonal is created", orthogonalkey.c_str());
76 }
77 else
78 {
79 ROS_WARN_STREAM("There were already one existing orthogonal of type "
80 << orthogonalkey.c_str() << ". Skipping creation orthogonal request. ");
81 std::stringstream ss;
82 ss << "The existing orthogonals are the following: " << std::endl;
83 for (auto &orthogonal : orthogonals_)
84 {
85 ss << " - " << orthogonal.first << std::endl;
86 }
87 ROS_WARN_STREAM(ss.str());
88 }
89 this->unlockStateMachine("create orthogonal");
90 }
91
92 //-------------------------------------------------------------------------------------------------------
93 template <typename SmaccComponentType>
94 void ISmaccStateMachine::requiresComponent(SmaccComponentType *&storage)
95 {
96 ROS_DEBUG("component %s is required", demangleSymbol(typeid(SmaccComponentType).name()).c_str());
97 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
98
99 for (auto ortho : this->orthogonals_)
100 {
101 for (auto &client : ortho.second->clients_)
102 {
103
104 storage = client->getComponent<SmaccComponentType>();
105 if (storage != nullptr)
106 {
107 return;
108 }
109 }
110 }
111
112 ROS_WARN("component %s is required but it was not found in any orthogonal", demangleSymbol(typeid(SmaccComponentType).name()).c_str());
113
114 // std::string componentkey = demangledTypeName<SmaccComponentType>();
115 // SmaccComponentType *ret;
116
117 // auto it = components_.find(componentkey);
118
119 // if (it == components_.end())
120 // {
121 // ROS_DEBUG("%s smacc component is required. Creating a new instance.", componentkey.c_str());
122
123 // ret = new SmaccComponentType();
124 // ret->setStateMachine(this);
125 // components_[componentkey] = static_cast<smacc::ISmaccComponent *>(ret);
126 // ROS_DEBUG("%s resource is required. Done.", componentkey.c_str());
127 // }
128 // else
129 // {
130 // ROS_DEBUG("%s resource is required. Found resource in cache.", componentkey.c_str());
131 // ret = dynamic_cast<SmaccComponentType *>(it->second);
132 // }
133
134 // storage = ret;
135 }
136 //-------------------------------------------------------------------------------------------------------
137 template <typename EventType>
138 void ISmaccStateMachine::postEvent(EventType *ev, EventLifeTime evlifetime)
139 {
140 std::lock_guard<std::recursive_mutex> guard(eventQueueMutex_);
143 {
144 ROS_WARN_STREAM("CURRENT STATE SCOPED EVENT SKIPPED, state is exiting/transitioning " << demangleSymbol<EventType>());
145 return;
146 // in this case we may lose/skip events, if this is not right for some cases we should create a queue
147 // to lock the events during the transitions. This issues appeared when a client asyncbehavior was posting an event
148 // meanwhile we were doing the transition, but the main thread was waiting for its correct finalization (with thread.join)
149 }
150
151 // when a postting event is requested by any component, client, or client behavior
152 // we reach this place. Now, we propagate the events to all the state state reactors to generate
153 // some more events
154
155 ROS_DEBUG_STREAM("[PostEvent entry point] " << demangleSymbol<EventType>());
156
157 for (auto currentState : currentState_)
158 {
159 propagateEventToStateReactors(currentState, ev);
160 }
161
162 this->signalDetector_->postEvent(ev);
163 }
164
165 template <typename EventType>
167 {
168 auto *ev = new EventType();
169 this->postEvent(ev, evlifetime);
170 }
171
172 template <typename T>
173 bool ISmaccStateMachine::getGlobalSMData(std::string name, T &ret)
174 {
175 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
176 // ROS_WARN("get SM Data lock acquire");
177 bool success = false;
178
179 if (!globalData_.count(name))
180 {
181 // ROS_WARN("get SM Data - data do not exist");
182 success = false;
183 }
184 else
185 {
186 // ROS_WARN("get SM DAta -data exist. accessing");
187 try
188 {
189 auto &v = globalData_[name];
190
191 // ROS_WARN("get SM DAta -data exist. any cast");
192 ret = boost::any_cast<T>(v.second);
193 success = true;
194 // ROS_WARN("get SM DAta -data exist. success");
195 }
196 catch (boost::bad_any_cast &ex)
197 {
198 ROS_ERROR("bad any cast: %s", ex.what());
199 success = false;
200 }
201 }
202
203 // ROS_WARN("get SM Data lock release");
204 return success;
205 }
206
207 template <typename T>
208 void ISmaccStateMachine::setGlobalSMData(std::string name, T value)
209 {
210 {
211 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
212 // ROS_WARN("set SM Data lock acquire");
213
214 globalData_[name] = {[this, name]() {
215 std::stringstream ss;
216 auto val = any_cast<T>(globalData_[name].second);
217 ss << val;
218 return ss.str();
219 },
220 value};
221 }
222
223 this->updateStatusMessage();
224 }
225
226 template <typename StateField, typename BehaviorType>
228 {
229 std::string stateFieldName = demangleSymbol(typeid(StateField).name());
230 std::string behaviorType = demangleSymbol(typeid(BehaviorType).name());
231 ROS_INFO("Mapping state field '%s' to stateReactor '%s'", stateFieldName.c_str(), behaviorType.c_str());
232 SmaccClientBehavior *globalreference;
233 if (!this->getGlobalSMData(stateFieldName, globalreference))
234 {
235 // Using the requires component approach, we force a unique existence
236 // of this component
237 BehaviorType *behavior;
238 this->requiresComponent(behavior);
239 globalreference = dynamic_cast<ISmaccClientBehavior *>(behavior);
240
241 this->setGlobalSMData(stateFieldName, globalreference);
242 }
243 }
244
245 namespace utils
246 {
247 template <int arity>
248 struct Bind
249 {
250 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
251 boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback,
252 TSmaccObjectType *object, std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
253 };
254
255 template <>
256 struct Bind<1>
257 {
258 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
259 boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
260 {
261 return signal.connect(
262
263 [=]()
264 {
265 if(callbackCounter == nullptr)
266 {
267 (object->*callback)();
268 }
269 else if (callbackCounter->acquire())
270 {
271 (object->*callback)();
272 callbackCounter->release();
273 }});
274 }
275 };
276
277 template <>
278 struct Bind<2>
279 {
280 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
281 boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
282 {
283 return signal.connect([=](auto a1)
284 {
285 if(callbackCounter == nullptr)
286 {
287 (object->*callback)(a1);
288 }
289 else if (callbackCounter->acquire())
290 {
291 (object->*callback)(a1);
292 callbackCounter->release();
293
294 }
295 });
296 }
297 };
298
299 template <>
300 struct Bind<3>
301 {
302 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
303 boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
304 {
305 return signal.connect([=](auto a1, auto a2) {
306 if(callbackCounter == nullptr)
307 {
308 (object->*callback)(a1,a2);
309 }
310 else if (callbackCounter->acquire())
311 {
312 (object->*callback)(a1,a2);
313 callbackCounter->release();
314
315 }
316 });
317 }
318 };
319
320 template <>
321 struct Bind<4>
322 {
323 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
324 boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
325 {
326 return signal.connect([=](auto a1, auto a2, auto a3) {
327 if(callbackCounter == nullptr)
328 {
329 (object->*callback)(a1,a2,a3);
330 }
331 else if (callbackCounter->acquire())
332 {
333 (object->*callback)(a1,a2,a3);
334 callbackCounter->release();
335
336 }
337 });
338
339 }
340 };
341 } // namespace utils
342 using namespace smacc::utils;
343
344 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
345 boost::signals2::connection ISmaccStateMachine::createSignalConnection(TSmaccSignal &signal,
346 TMemberFunctionPrototype callback,
347 TSmaccObjectType *object)
348 {
349 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
350
351 static_assert(std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
352 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
353 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value ||
354 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
355 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value,
356 "Only are accepted smacc types as subscribers for smacc signals");
357
358 typedef decltype(callback) ft;
360
361 boost::signals2::connection connection;
362
363 // long life-time objects
364 if (std::is_base_of<ISmaccComponent, TSmaccObjectType>::value ||
365 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
366 std::is_base_of<ISmaccOrthogonal, TSmaccObjectType>::value ||
367 std::is_base_of<ISmaccStateMachine, TSmaccObjectType>::value)
368 {
369 connection = binder.bindaux(signal, callback, object, nullptr);
370 }
371 else if (std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
372 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
373 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
374 {
375 ROS_INFO("[StateMachine] life-time constrained smacc signal subscription created. Subscriber is %s",
376 demangledTypeName<TSmaccObjectType>().c_str());
377
378 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
379 if(stateCallbackConnections.count(object))
380 {
381 callbackCounterSemaphore = stateCallbackConnections[object];
382 }
383 else
384 {
385 callbackCounterSemaphore = std::make_shared<CallbackCounterSemaphore>(demangledTypeName<TSmaccObjectType>().c_str());
386 stateCallbackConnections[object] = callbackCounterSemaphore;
387 }
388
389 connection = binder.bindaux(signal, callback, object, callbackCounterSemaphore);
390 callbackCounterSemaphore->addConnection(connection);
391
392 }
393 else // state life-time objects
394 {
395 ROS_WARN("[StateMachine] connecting signal to an unknown object with life-time unknown behavior. It might provoke "
396 "an exception if the object is destroyed during the execution.");
397
398 connection = binder.bindaux(signal, callback, object, nullptr);
399 }
400
401 return connection;
402 }
403
404 template <typename T>
405 bool ISmaccStateMachine::getParam(std::string param_name, T &param_storage)
406 {
407 return nh_.getParam(param_name, param_storage);
408 }
409
410 // Delegates to ROS param access with the current NodeHandle
411 template <typename T>
412 void ISmaccStateMachine::setParam(std::string param_name, T param_val)
413 {
414 return nh_.setParam(param_name, param_val);
415 }
416
417 // Delegates to ROS param access with the current NodeHandle
418 template <typename T>
419 bool ISmaccStateMachine::param(std::string param_name, T &param_val, const T &default_val) const
420 {
421 return nh_.param(param_name, param_val, default_val);
422 }
423
424 template <typename StateType>
426 {
427 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
428
429 ROS_DEBUG("[State Machne] Initializating a new state '%s' and updating current state. Getting state meta-information. number of orthogonals: %ld", demangleSymbol(typeid(StateType).name()).c_str(), this->orthogonals_.size());
430
432 currentState_.push_back(state);
433 currentStateInfo_ = stateMachineInfo_->getState<StateType>();
434 }
435
436 template <typename StateType>
438 {
439 ROS_INFO("[%s] State OnEntry code finished", demangleSymbol(typeid(StateType).name()).c_str());
440
441 auto currentState = this->currentState_.back();
442 for (auto pair : this->orthogonals_)
443 {
444 //ROS_INFO("ortho onentry: %s", pair.second->getName().c_str());
445 auto &orthogonal = pair.second;
446 try
447 {
448 orthogonal->onEntry();
449 }
450 catch (const std::exception &e)
451 {
452 ROS_ERROR("[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
453 pair.second->getName().c_str(), e.what());
454 }
455 }
456
457 for (auto &sr : currentState->getStateReactors())
458 {
459 auto srname = smacc::demangleSymbol(typeid(*sr).name()).c_str();
460 ROS_INFO("state reactor onEntry: %s", srname);
461 try
462 {
463 sr->onEntry();
464 }
465 catch (const std::exception &e)
466 {
467 ROS_ERROR("[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception info: %s",
468 srname, e.what());
469 }
470 }
471
472 for (auto &eg : currentState->getEventGenerators())
473 {
474 auto egname = smacc::demangleSymbol(typeid(*eg).name()).c_str();
475 ROS_INFO("state reactor onEntry: %s", egname);
476 try
477 {
478 eg->onEntry();
479 }
480 catch (const std::exception &e)
481 {
482 ROS_ERROR("[Event generator %s] Exception on Entry - continuing with next state reactor. Exception info: %s",
483 egname, e.what());
484 }
485 }
486
487 {
488 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
489 this->updateStatusMessage();
491 }
492 }
493
494 template <typename StateType>
496 {
497 for (auto pair : this->orthogonals_)
498 {
499 //ROS_INFO("ortho onruntime configure: %s", pair.second->getName().c_str());
500 auto &orthogonal = pair.second;
501 orthogonal->runtimeConfigure();
502 }
503
504 {
505 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
506 this->updateStatusMessage();
508
510 }
511 }
512
513 template <typename StateType>
515 {
517 }
518
519 template <typename StateType>
521 {
523
524 auto fullname = demangleSymbol(typeid(StateType).name());
525 ROS_WARN_STREAM("exiting state: " << fullname);
526 //this->setParam("destroyed", true);
527
528 ROS_INFO_STREAM("Notification State Exit: leaving state" << state);
529 for (auto pair : this->orthogonals_)
530 {
531 auto &orthogonal = pair.second;
532 try
533 {
534 orthogonal->onExit();
535 }
536 catch (const std::exception &e)
537 {
538 ROS_ERROR("[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
539 pair.second->getName().c_str(), e.what());
540 }
541 }
542
543 for (auto &sr : state->getStateReactors())
544 {
545 auto srname = smacc::demangleSymbol(typeid(*sr).name()).c_str();
546 ROS_INFO("state reactor OnExit: %s", srname);
547 try
548 {
549 sr->onExit();
550 }
551 catch (const std::exception &e)
552 {
553 ROS_ERROR("[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception info: %s",
554 srname, e.what());
555 }
556 }
557
558 for (auto &eg : state->getEventGenerators())
559 {
560 auto egname = smacc::demangleSymbol(typeid(*eg).name()).c_str();
561 ROS_INFO("state reactor OnExit: %s", egname);
562 try
563 {
564 eg->onExit();
565 }
566 catch (const std::exception &e)
567 {
568 ROS_ERROR("[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception info: %s",
569 egname, e.what());
570 }
571 }
572 }
573
574 template <typename StateType>
576 {
577 this->lockStateMachine("state exit");
578
580
581 auto fullname = demangleSymbol(typeid(StateType).name());
582 ROS_WARN_STREAM("exiting state: " << fullname);
583
584 ROS_INFO_STREAM("Notification State Disposing: leaving state" << state);
585 for (auto pair : this->orthogonals_)
586 {
587 auto &orthogonal = pair.second;
588 try
589 {
590 orthogonal->onDispose();
591 }
592 catch (const std::exception &e)
593 {
594 ROS_ERROR("[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
595 pair.second->getName().c_str(), e.what());
596 }
597 }
598
599 for (auto &sr : state->getStateReactors())
600 {
601 auto srname = smacc::demangleSymbol(typeid(*sr).name()).c_str();
602 ROS_INFO("state reactor disposing: %s", srname);
603 try
604 {
605 this->disconnectSmaccSignalObject(sr.get());
606 }
607 catch (const std::exception &e)
608 {
609 ROS_ERROR("[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception info: %s",
610 srname, e.what());
611 }
612 }
613
614 for (auto &eg : state->getEventGenerators())
615 {
616 auto egname = smacc::demangleSymbol(typeid(*eg).name()).c_str();
617 ROS_INFO("state reactor disposing: %s", egname);
618 try
619 {
620 this->disconnectSmaccSignalObject(eg.get());
621 }
622 catch (const std::exception &e)
623 {
624 ROS_ERROR("[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception info: %s",
625 egname, e.what());
626 }
627 }
628
629 this->stateCallbackConnections.clear();
630 currentState_.pop_back();
631
632 // then call exit state
633 ROS_WARN_STREAM("state exit: " << fullname);
634
636 this->unlockStateMachine("state exit");
637 }
638 //-------------------------------------------------------------------------------------------------------
639 template <typename EventType>
641 {
642 ROS_DEBUG("PROPAGATING EVENT [%s] TO LUs [%s]: ", demangleSymbol<EventType>().c_str(), st->getClassName().c_str());
643 for (auto &sb : st->getStateReactors())
644 {
645 sb->notifyEvent(ev);
646 }
647
648 auto *pst = st->getParentState();
649 if (pst != nullptr)
650 {
652 }
653 }
654
655 template <typename InitialStateType>
657 {
658 this->stateMachineInfo_ = std::make_shared<SmaccStateMachineInfo>();
659 this->stateMachineInfo_->buildStateMachineInfo<InitialStateType>();
660 this->stateMachineInfo_->assembleSMStructureMessage(this);
662 }
663
665 {
666 return this->stateSeqCounter_;
667 }
668
670 {
671 return this->currentState_.back();
672 }
673
675 {
676 return *this->stateMachineInfo_;
677 }
678
679} // namespace smacc
std::shared_ptr< SmaccStateMachineInfo > stateMachineInfo_
void notifyOnRuntimeConfigurationFinished(StateType *state)
bool param(std::string param_name, T &param_val, const T &default_val) const
const SmaccStateMachineInfo & getStateMachineInfo()
void propagateEventToStateReactors(ISmaccState *st, EventType *ev)
std::vector< ISmaccState * > currentState_
std::recursive_mutex eventQueueMutex_
void lockStateMachine(std::string msg)
ISmaccState * getCurrentState() const
StateMachineInternalAction stateMachineCurrentAction
void notifyOnStateExitting(StateType *state)
void notifyOnRuntimeConfigured(StateType *state)
void notifyOnStateEntryEnd(StateType *state)
void setGlobalSMData(std::string name, T value)
std::shared_ptr< SmaccStateInfo > currentStateInfo_
std::map< void *, std::shared_ptr< CallbackCounterSemaphore > > stateCallbackConnections
void requiresComponent(SmaccComponentType *&storage)
std::recursive_mutex m_mutex_
void notifyOnStateExited(StateType *state)
bool getParam(std::string param_name, T &param_storage)
std::map< std::string, std::shared_ptr< smacc::ISmaccOrthogonal > > orthogonals_
std::map< std::string, std::pair< std::function< std::string()>, boost::any > > globalData_
boost::signals2::connection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
void unlockStateMachine(std::string msg)
void disconnectSmaccSignalObject(void *object)
bool getGlobalSMData(std::string name, T &ret)
void notifyOnStateEntryStart(StateType *state)
void setParam(std::string param_name, T param_val)
void postEvent(EventType *ev, EventLifeTime evlifetime=EventLifeTime::ABSOLUTE)
ISmaccState * getParentState()
Definition: smacc_state.h:16
virtual std::string getClassName()
Definition: smacc_state.cpp:6
std::vector< std::shared_ptr< StateReactor > > & getStateReactors()
Definition: smacc_state.h:60
void notifyStateConfigured(ISmaccState *currentState)
void postEvent(EventType *ev)
void notifyStateExited(ISmaccState *currentState)
std::string demangleSymbol()
Definition: introspection.h:75
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
boost::signals2::connection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)