SMACC2
Loading...
Searching...
No Matches
smacc_state_machine_impl.hpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/**************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 **************************************************************************************************/
20
21#pragma once
22
23#include <memory>
24#include <sstream>
25#include <string>
26
35
36#include <boost/function_types/function_arity.hpp>
37#include <boost/function_types/function_type.hpp>
38#include <boost/function_types/parameter_types.hpp>
40#include <smacc2_msgs/msg/smacc_status.hpp>
41
42namespace smacc2
43{
44using namespace smacc2::introspection;
45
46template <typename TOrthogonal>
48{
49 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
50
51 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
52 TOrthogonal * ret;
53
54 auto it = orthogonals_.find(orthogonalkey);
55
56 if (it != orthogonals_.end())
57 {
58 RCLCPP_DEBUG(
59 getLogger(),
60 "Orthogonal %s resource is being required from some state, client or component. Found "
61 "resource in "
62 "cache.",
63 orthogonalkey.c_str());
64 ret = dynamic_cast<TOrthogonal *>(it->second.get());
65 return ret;
66 }
67 else
68 {
69 std::stringstream ss;
70 ss << "Orthogonal not found " << orthogonalkey.c_str() << std::endl;
71 ss << "The existing orthogonals are the following: " << std::endl;
72 for (auto & orthogonal : orthogonals_)
73 {
74 ss << " - " << orthogonal.first << std::endl;
75 }
76
77 RCLCPP_WARN_STREAM(getLogger(), ss.str());
78
79 return nullptr;
80 }
81}
82
83//-------------------------------------------------------------------------------------------------------
84template <typename TOrthogonal>
86{
87 std::lock_guard<std::recursive_mutex> guard(m_mutex_);
88
89 std::string orthogonalkey = demangledTypeName<TOrthogonal>();
90
91 if (orthogonals_.count(orthogonalkey) == 0)
92 {
93 auto ret = std::make_shared<TOrthogonal>();
94 orthogonals_[orthogonalkey] = dynamic_pointer_cast<smacc2::ISmaccOrthogonal>(ret);
95
96 ret->setStateMachine(this);
97
98 RCLCPP_INFO(getLogger(), "%s Orthogonal is created", orthogonalkey.c_str());
99 }
100 else
101 {
102 RCLCPP_WARN_STREAM(
103 getLogger(), "There were already one existing orthogonal of type "
104 << orthogonalkey.c_str() << ". Skipping creation orthogonal request. ");
105 std::stringstream ss;
106 ss << "The existing orthogonals are the following: " << std::endl;
107 for (auto & orthogonal : orthogonals_)
108 {
109 ss << " - " << orthogonal.first << std::endl;
110 }
111 RCLCPP_WARN_STREAM(getLogger(), ss.str());
112 }
113}
114
115//-------------------------------------------------------------------------------------------------------
116template <typename SmaccComponentType>
118 SmaccComponentType *& storage, ComponentRequirement requirementType)
119{
120 bool throwsException = requirementType == ComponentRequirement::HARD;
121 RCLCPP_DEBUG(
122 getLogger(), "component %s is required",
123 demangleSymbol(typeid(SmaccComponentType).name()).c_str());
124 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
125
126 for (auto ortho : this->orthogonals_)
127 {
128 for (auto & client : ortho.second->clients_)
129 {
130 storage = client->getComponent<SmaccComponentType>();
131 if (storage != nullptr)
132 {
133 return;
134 }
135 }
136 }
137
138 RCLCPP_WARN(
139 getLogger(), "component %s is required but it was not found in any orthogonal",
140 demangleSymbol(typeid(SmaccComponentType).name()).c_str());
141
142 if (throwsException)
143 throw std::runtime_error("component is required but it was not found in any orthogonal");
144}
145//-------------------------------------------------------------------------------------------------------
146template <typename EventType>
147void ISmaccStateMachine::postEvent(EventType * ev, EventLifeTime evlifetime)
148{
149 std::lock_guard<std::recursive_mutex> guard(eventQueueMutex_);
150
151#define eventtypename demangleSymbol<EventType>().c_str()
152
153 TRACETOOLS_TRACEPOINT(smacc2_event, eventtypename);
154
155 {
157 EventLabel<EventType>(evinfo.label);
158
159 smacc2_msgs::msg::SmaccEvent event;
160 event.event_type = evinfo.getEventTypeName();
161 event.event_source = evinfo.getEventSourceName();
162 event.event_object_tag = evinfo.getOrthogonalName();
163 event.label = evinfo.label;
164
165 if (this->eventsLogPub_)
166 {
167 this->eventsLogPub_->publish(event);
168 }
169 }
170
171 if (
172 evlifetime == EventLifeTime::CURRENT_STATE &&
175 {
176 RCLCPP_WARN_STREAM(
177 getLogger(),
178 "[ISmaccStateMachine] CURRENT STATE SCOPED EVENT DISCARDED, state is exiting/transitioning "
179 << eventtypename);
180 return;
181 // in this case we may lose/skip events, if this is not right for some cases we should create a
182 // queue to lock the events during the transitions. This issues appeared when a client
183 // asyncbehavior was posting an event meanwhile we were doing the transition, but the main
184 // thread was waiting for its correct finalization (with thread.join)
185 }
186
187 // when a postting event is requested by any component, client, or client behavior
188 // we reach this place. Now, we propagate the events to all the state state reactors to generate
189 // some more events
190
191 RCLCPP_DEBUG_STREAM(getLogger(), "[PostEvent entry point] " << eventtypename);
192 if (!currentState_.empty())
193 {
195 }
196
197 this->signalDetector_->postEvent(ev);
198}
199
200template <typename EventType>
202{
204 RCLCPP_INFO_STREAM(getLogger(), "Event: " << evname);
205 auto * ev = new EventType();
206 this->postEvent(ev, evlifetime);
207}
208
209template <typename T>
210bool ISmaccStateMachine::getGlobalSMData(std::string name, T & ret)
211{
212 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
213 // RCLCPP_WARN(getLogger(),"get SM Data lock acquire");
214 bool success = false;
215
216 if (!globalData_.count(name))
217 {
218 // RCLCPP_WARN(getLogger(),"get SM Data - data do not exist");
219 success = false;
220 }
221 else
222 {
223 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. accessing");
224 try
225 {
226 auto & v = globalData_[name];
227
228 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. any cast");
229 ret = boost::any_cast<T>(v.second);
230 success = true;
231 // RCLCPP_WARN(getLogger(),"get SM DAta -data exist. success");
232 }
233 catch (boost::bad_any_cast & ex)
234 {
235 RCLCPP_ERROR(getLogger(), "bad any cast: %s", ex.what());
236 success = false;
237 }
238 }
239
240 // RCLCPP_WARN(getLogger(),"get SM Data lock release");
241 return success;
242}
243
244template <typename T>
245void ISmaccStateMachine::setGlobalSMData(std::string name, T value)
246{
247 {
248 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
249 // RCLCPP_WARN(getLogger(),"set SM Data lock acquire");
250
251 globalData_[name] = {
252 [this, name]()
253 {
254 std::stringstream ss;
255 auto val = any_cast<T>(globalData_[name].second);
256 ss << val;
257 return ss.str();
258 },
259 value};
260 }
261
262 this->updateStatusMessage();
263}
264
265namespace utils
266{
267template <int arity>
268struct Bind
269{
270 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
272 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
273 std::shared_ptr<CallbackCounterSemaphore> callbackCounter);
274};
275
276template <>
277struct Bind<1>
278{
279 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
281 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
282 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
283 {
284 return signal.connect(
285
286 [=]()
287 {
288 if (callbackCounter == nullptr)
289 {
290 (object->*callback)();
291 }
292 else if (callbackCounter->acquire())
293 {
294 (object->*callback)();
295 callbackCounter->release();
296 }
297 });
298 }
299};
300
301template <>
302struct Bind<2>
303{
304 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
306 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
307 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
308 {
309 return signal.connect(
310 [=](auto a1)
311 {
312 if (callbackCounter == nullptr)
313 {
314 return (object->*callback)(a1);
315 }
316 else if (callbackCounter->acquire())
317 {
318 (object->*callback)(a1);
319 callbackCounter->release();
320 }
321 });
322 }
323};
324
325template <>
326struct Bind<3>
327{
328 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
330 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
331 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
332 {
333 return signal.connect(
334 [=](auto a1, auto a2)
335 {
336 if (callbackCounter == nullptr)
337 {
338 return (object->*callback)(a1, a2);
339 }
340 else if (callbackCounter->acquire())
341 {
342 (object->*callback)(a1, a2);
343 callbackCounter->release();
344 }
345 });
346 }
347};
348
349template <>
350struct Bind<4>
351{
352 template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
354 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object,
355 std::shared_ptr<CallbackCounterSemaphore> callbackCounter)
356 {
357 return signal.connect(
358 [=](auto a1, auto a2, auto a3)
359 {
360 if (callbackCounter == nullptr)
361 {
362 return (object->*callback)(a1, a2, a3);
363 }
364 else if (callbackCounter->acquire())
365 {
366 (object->*callback)(a1, a2, a3);
367 callbackCounter->release();
368 }
369 });
370 }
371};
372} // namespace utils
373using namespace smacc2::utils;
374
375template <typename TSmaccSignal, typename TMemberFunctionPrototype, typename TSmaccObjectType>
377 TSmaccSignal & signal, TMemberFunctionPrototype callback, TSmaccObjectType * object)
378{
379 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
380
381 static_assert(
382 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
383 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
384 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value ||
385 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
386 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value,
387 "Only are accepted smacc types as subscribers for smacc signals");
388
389 typedef decltype(callback) ft;
392
393 // long life-time objects
394 if (
395 std::is_base_of<ISmaccComponent, TSmaccObjectType>::value ||
396 std::is_base_of<ISmaccClient, TSmaccObjectType>::value ||
397 std::is_base_of<ISmaccOrthogonal, TSmaccObjectType>::value ||
398 std::is_base_of<ISmaccStateMachine, TSmaccObjectType>::value)
399 {
400 RCLCPP_INFO(
401 getLogger(),
402 "[StateMachine] Long life-time SMACC signal subscription created. Subscriber is %s. Callback "
403 "is: %s",
405 demangleSymbol(typeid(callback).name()).c_str());
406
407 connection = binder.bindaux(signal, callback, object, nullptr);
408 }
409 else if (
410 std::is_base_of<ISmaccState, TSmaccObjectType>::value ||
411 std::is_base_of<StateReactor, TSmaccObjectType>::value ||
412 std::is_base_of<ISmaccClientBehavior, TSmaccObjectType>::value)
413 {
414 RCLCPP_INFO(
415 getLogger(),
416 "[StateMachine] Life-time constrained SMACC signal subscription created. Subscriber is %s",
418
419 std::shared_ptr<CallbackCounterSemaphore> callbackCounterSemaphore;
420 if (stateCallbackConnections.count(object))
421 {
422 callbackCounterSemaphore = stateCallbackConnections[object];
423 }
424 else
425 {
426 callbackCounterSemaphore =
427 std::make_shared<CallbackCounterSemaphore>(demangledTypeName<TSmaccObjectType>().c_str());
428 stateCallbackConnections[object] = callbackCounterSemaphore;
429 }
430
431 connection = binder.bindaux(signal, callback, object, callbackCounterSemaphore);
432 callbackCounterSemaphore->addConnection(connection);
433 }
434 else // state life-time objects
435 {
436 RCLCPP_WARN(
437 getLogger(),
438 "[StateMachine] Connecting signal to an unknown object with unknown lifetime "
439 "behavior. An exception may occur if the object is destroyed during the execution.");
440
441 connection = binder.bindaux(signal, callback, object, nullptr);
442 }
443
444 return connection;
445}
446
447template <typename StateType>
449{
450 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
451
452 RCLCPP_DEBUG(
453 getLogger(),
454 "[State Machine] Initializing a new state '%s' and updating current state. Getting state "
455 "meta-information. number of orthogonals: %ld",
456 demangleSymbol(typeid(StateType).name()).c_str(), this->orthogonals_.size());
457
459 currentState_.push_back(state);
460 currentStateInfo_ = stateMachineInfo_->getState<StateType>();
461}
462
463template <typename StateType>
465{
466 RCLCPP_INFO(
467 getLogger(), "[%s] State OnEntry code finished.",
468 demangleSymbol(typeid(StateType).name()).c_str());
469
470 auto currentState = this->currentState_.back();
471 for (auto pair : this->orthogonals_)
472 {
473 RCLCPP_DEBUG(getLogger(), "Orthogonal onEntry: %s.", pair.second->getName().c_str());
474 auto & orthogonal = pair.second;
475 try
476 {
477 orthogonal->onEntry();
478 }
479 catch (const std::exception & e)
480 {
481 RCLCPP_ERROR(
482 getLogger(),
483 "[Orthogonal %s] Exception on Entry - continuing with next orthogonal. Exception info: %s",
484 pair.second->getName().c_str(), e.what());
485 }
486 }
487
488 for (auto & sr : currentState->getStateReactors())
489 {
490 auto srname = smacc2::demangleSymbol(typeid(*sr).name());
491 RCLCPP_INFO_STREAM(getLogger(), "State reactor onEntry: " << srname);
492 try
493 {
494 sr->onEntry();
495 }
496 catch (const std::exception & e)
497 {
498 RCLCPP_ERROR(
499 getLogger(),
500 "[State Reactor %s] Exception on Entry - continuing with next state reactor. Exception "
501 "info: %s",
502 srname.c_str(), e.what());
503 }
504 }
505
506 for (auto & eg : currentState->getEventGenerators())
507 {
508 auto egname = smacc2::demangleSymbol(typeid(*eg).name());
509 RCLCPP_INFO_STREAM(getLogger(), "Event generator onEntry: " << egname);
510 try
511 {
512 eg->onEntry();
513 }
514 catch (const std::exception & e)
515 {
516 RCLCPP_ERROR(
517 getLogger(),
518 "[Event generator %s] Exception on Entry - continuing with next state reactor. Exception "
519 "info: %s",
520 egname.c_str(), e.what());
521 }
522 }
523
524 {
525 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
526 this->updateStatusMessage();
528 }
529}
530
531template <typename StateType>
533{
534 for (auto pair : this->orthogonals_)
535 {
536 // RCLCPP_INFO(getLogger(),"ortho onruntime configure: %s", pair.second->getName().c_str());
537 auto & orthogonal = pair.second;
538 orthogonal->runtimeConfigure();
539 }
540
541 {
542 std::lock_guard<std::recursive_mutex> lock(m_mutex_);
543 this->updateStatusMessage();
545
547 }
548}
549
550template <typename StateType>
555
556template <typename StateType>
558{
560 auto fullname = demangleSymbol(typeid(StateType).name());
561 RCLCPP_WARN_STREAM(getLogger(), "Exiting state: " << fullname);
562
563 RCLCPP_INFO_STREAM(getLogger(), "Notification state exit: leaving state " << state);
564 for (auto pair : this->orthogonals_)
565 {
566 auto & orthogonal = pair.second;
567 try
568 {
569 orthogonal->onExit();
570 }
571 catch (const std::exception & e)
572 {
573 RCLCPP_ERROR(
574 getLogger(),
575 "[Orthogonal %s] Exception onExit - continuing with next orthogonal. Exception info: %s",
576 pair.second->getName().c_str(), e.what());
577 }
578 }
579
580 for (auto & sr : state->getStateReactors())
581 {
582 auto srname = smacc2::demangleSymbol(typeid(*sr).name());
583 RCLCPP_INFO_STREAM(getLogger(), "State reactor OnExit: " << srname);
584 try
585 {
586 sr->onExit();
587 }
588 catch (const std::exception & e)
589 {
590 RCLCPP_ERROR(
591 getLogger(),
592 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
593 "info: %s",
594 srname.c_str(), e.what());
595 }
596 }
597
598 for (auto & eg : state->getEventGenerators())
599 {
600 auto egname = smacc2::demangleSymbol(typeid(*eg).name());
601 RCLCPP_INFO_STREAM(getLogger(), "Event generator OnExit: " << egname);
602 try
603 {
604 eg->onExit();
605 }
606 catch (const std::exception & e)
607 {
608 RCLCPP_ERROR(
609 getLogger(),
610 "[State Reactor %s] Exception on OnExit - continuing with next state reactor. Exception "
611 "info: %s",
612 egname.c_str(), e.what());
613 }
614 }
615}
616
617template <typename StateType>
619{
620 this->lockStateMachine("state exit");
621
623
624 auto fullname = demangleSymbol(typeid(StateType).name());
625 RCLCPP_WARN_STREAM(getLogger(), "Exiting state: " << fullname);
626
627 RCLCPP_INFO_STREAM(getLogger(), "Notification state disposing: leaving state" << state);
628 for (auto pair : this->orthogonals_)
629 {
630 auto & orthogonal = pair.second;
631 try
632 {
633 orthogonal->onDispose();
634 }
635 catch (const std::exception & e)
636 {
637 RCLCPP_ERROR(
638 getLogger(),
639 "[Orthogonal %s] Exception onDispose - continuing with next orthogonal. Exception info: %s",
640 pair.second->getName().c_str(), e.what());
641 }
642 }
643
644 for (auto & sr : state->getStateReactors())
645 {
646 auto srname = smacc2::demangleSymbol(typeid(*sr).name()).c_str();
647 RCLCPP_INFO(getLogger(), "State reactor disposing: %s", srname);
648 try
649 {
650 this->disconnectSmaccSignalObject(sr.get());
651 }
652 catch (const std::exception & e)
653 {
654 RCLCPP_ERROR(
655 getLogger(),
656 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
657 "info: %s",
658 srname, e.what());
659 }
660 }
661
662 for (auto & eg : state->getEventGenerators())
663 {
664 auto egname = smacc2::demangleSymbol(typeid(*eg).name()).c_str();
665 RCLCPP_INFO(getLogger(), "Event generator disposing: %s", egname);
666 try
667 {
668 this->disconnectSmaccSignalObject(eg.get());
669 }
670 catch (const std::exception & e)
671 {
672 RCLCPP_ERROR(
673 getLogger(),
674 "[State Reactor %s] Exception on OnDispose - continuing with next state reactor. Exception "
675 "info: %s",
676 egname, e.what());
677 }
678 }
679
680 this->stateCallbackConnections.clear();
681 currentState_.pop_back();
682
683 // then call exit state
684 RCLCPP_WARN_STREAM(getLogger(), "State exit: " << fullname);
685
687 this->unlockStateMachine("state exit");
688}
689//------------------------------------------------------------------------------------------------
690template <typename EventType>
692{
693 RCLCPP_DEBUG(
694 getLogger(), "PROPAGATING EVENT [%s] TO SRs [%s]: ", demangleSymbol<EventType>().c_str(),
695 st->getClassName().c_str());
696 for (auto & sb : st->getStateReactors())
697 {
698 sb->notifyEvent(ev);
699 }
700
701 auto * pst = st->getParentState();
702 if (pst != nullptr)
703 {
705 }
706}
707
708template <typename InitialStateType>
710{
711 this->stateMachineInfo_ = std::make_shared<SmaccStateMachineInfo>(this->getNode());
712 this->stateMachineInfo_->buildStateMachineInfo<InitialStateType>();
713 this->stateMachineInfo_->assembleSMStructureMessage(this);
715}
716
718
720
725
726} // namespace smacc2
std::map< std::string, std::shared_ptr< smacc2::ISmaccOrthogonal > > orthogonals_
std::vector< ISmaccState * > currentState_
std::recursive_mutex eventQueueMutex_
bool getGlobalSMData(std::string name, T &ret)
StateMachineInternalAction stateMachineCurrentAction
std::shared_ptr< SmaccStateInfo > currentStateInfo_
rclcpp::Node::SharedPtr getNode()
std::map< std::string, std::pair< std::function< std::string()>, boost::any > > globalData_
void requiresComponent(SmaccComponentType *&storage, ComponentRequirement requirementType)
void setGlobalSMData(std::string name, T value)
void notifyOnRuntimeConfigurationFinished(StateType *state)
smacc2::SmaccSignalConnection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)
void notifyOnStateExited(StateType *state)
void lockStateMachine(std::string msg)
void notifyOnStateEntryEnd(StateType *state)
void propagateEventToStateReactors(ISmaccState *st, EventType *ev)
void disconnectSmaccSignalObject(void *object)
const SmaccStateMachineInfo & getStateMachineInfo()
void unlockStateMachine(std::string msg)
void notifyOnStateExiting(StateType *state)
std::map< void *, std::shared_ptr< CallbackCounterSemaphore > > stateCallbackConnections
void notifyOnRuntimeConfigured(StateType *state)
std::shared_ptr< SmaccStateMachineInfo > stateMachineInfo_
void postEvent(EventType *ev, EventLifeTime evlifetime=EventLifeTime::ABSOLUTE)
rclcpp::Publisher< smacc2_msgs::msg::SmaccEvent >::SharedPtr eventsLogPub_
void notifyOnStateEntryStart(StateType *state)
ISmaccState * getParentState()
virtual std::string getClassName()
std::vector< std::shared_ptr< StateReactor > > & getStateReactors()
void notifyStateExited(ISmaccState *currentState)
void notifyStateConfigured(ISmaccState *currentState)
static TypeInfo::Ptr getTypeInfoFromType()
std::enable_if< HasEventLabel< T >::value, void >::type EventLabel(std::string &label)
std::string demangleSymbol()
std::string demangledTypeName()
boost::signals2::connection SmaccSignalConnection
ComponentRequirement
Definition common.hpp:74
#define eventtypename
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2::SmaccSignalConnection bindaux(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object, std::shared_ptr< CallbackCounterSemaphore > callbackCounter)
smacc2_event