34#include <Ice/BuiltinSequences.h>
35#include <Ice/Identity.h>
36#include <Ice/LocalException.h>
37#include <Ice/ObjectAdapter.h>
38#include <IceStorm/IceStorm.h>
39#include <IceUtil/Shared.h>
40#include <IceUtil/UUID.h>
48#include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
49#include <ArmarXCore/interface/core/ManagedIceObjectDependencyBase.h>
50#include <ArmarXCore/interface/core/Profiler.h>
63 class NotRegisteredException;
64 class ObjectAdapterDeactivatedException;
80 impl->objectState = eManagedIceObjectCreated;
82 impl->enableProfilerFunction = &ManagedIceObject::Noop;
85 std::unique_ptr<ManagedIceObjectPlugin>&
89 return _plugins[{type, prefix}];
95 impl->name = other.impl->name;
96 impl->armarXManager = other.impl->armarXManager;
97 impl->iceManager =
nullptr;
98 impl->objectScheduler =
nullptr;
99 impl->objectState = eManagedIceObjectCreated;
100 impl->proxy =
nullptr;
101 impl->objectAdapter =
nullptr;
102 impl->connectivity = other.impl->connectivity;
103 impl->profiler = other.impl->profiler;
104 impl->enableProfilerFunction = &ManagedIceObject::Noop;
110 if (impl->name.empty())
120 const std::string& subObjectName)
122 return superObjectName +
"." + subObjectName;
133 for (
const auto& [name, task] : impl->periodicTasks)
140 impl->periodicTasks.clear();
146 return impl->objectAdapter;
159 throw LocalException(
"proxyName must not be empty.");
162 std::unique_lock lock(impl->connectivityMutex);
165 if (impl->connectivity.dependencies.find(name) != impl->connectivity.dependencies.end())
172 impl->connectivity.dependencies.insert(std::make_pair(name, proxyDependency));
182 throw LocalException(
"The proxy name must not be empty.");
185 if (
getState() < eManagedIceObjectStarting)
187 throw LocalException(
"Calling getProxy before component has been started");
190 if (addToDependencies)
198 std::vector<std::string>
203 std::vector<std::string> dependencies;
205 for (
auto& dependencie : con.dependencies)
207 ManagedIceObjectDependencyBasePtr& dep = dependencie.second;
209 if (!dep->getResolved())
211 dependencies.push_back(dep->getName());
223 case eManagedIceObjectCreated:
226 case eManagedIceObjectInitializing:
227 return "Initializing";
229 case eManagedIceObjectInitialized:
230 return "Initialized";
231 case eManagedIceObjectInitializationFailed:
232 return "InitializationFailed";
234 case eManagedIceObjectStarting:
237 case eManagedIceObjectStartingFailed:
238 return "StartingFailed";
240 case eManagedIceObjectStarted:
243 case eManagedIceObjectExiting:
246 case eManagedIceObjectExited:
257 std::unique_lock lock(impl->connectivityMutex);
260 if (std::find(impl->connectivity.usedTopics.begin(),
261 impl->connectivity.usedTopics.end(),
262 name) != impl->connectivity.usedTopics.end())
268 impl->connectivity.usedTopics.push_back(name);
269 impl->orderedTopicPublishing[name] = orderedPublishing;
273 if (
getState() >= eManagedIceObjectStarting)
275 getIceManager()->subscribeTopic(impl->proxy, name, orderedPublishing);
283 std::unique_lock lock(impl->connectivityMutex);
289 impl->connectivity.usedTopics.begin(), impl->connectivity.usedTopics.end(), name);
290 if (it != impl->connectivity.usedTopics.end())
292 impl->connectivity.usedTopics.erase(it);
303 std::unique_lock lock(impl->connectivityMutex);
306 if (std::find(impl->connectivity.offeredTopics.begin(),
307 impl->connectivity.offeredTopics.end(),
308 topicName) != impl->connectivity.offeredTopics.end())
314 impl->connectivity.offeredTopics.push_back(topicName);
315 ARMARX_INFO <<
"Offering topic with name: '" << topicName <<
"'";
318 if (
getState() >= eManagedIceObjectStarting)
327 if (
getState() < eManagedIceObjectStarting)
329 throw LocalException(
"Calling getTopic before component has been started");
340 std::unique_lock lock(impl->connectivityMutex);
343 DependencyMap::iterator it = impl->connectivity.dependencies.find(name);
345 if (it == impl->connectivity.dependencies.end())
350 ARMARX_VERBOSE <<
"Removing proxy '" << name <<
"' from dependency list.";
351 impl->connectivity.dependencies.erase(it);
362 return impl->armarXManager;
368 return impl->iceManager;
374 return impl->profiler;
383 impl->enableProfilerFunction = &ManagedIceObject::Noop;
387 impl->profiler->setLoggingStrategy(strategy);
397 ManagedIceObject::EnableProfilerOn(
this);
402 impl->enableProfilerFunction = &ManagedIceObject::EnableProfilerOn;
412 if (waitForScheduler)
424 oSched->waitForObjectStateMinimum(eManagedIceObjectStarting, timeoutMs);
428 ARMARX_WARNING_S <<
"called on an object without a object scheduler. To fix this add "
429 "the object to an ArmarXManager prior to calling this function.";
440 impl->stateCondition.notify_all();
441 impl->objectScheduler->terminate();
447 this->impl->name = name;
464 setObjectState(eManagedIceObjectInitializing);
467 this->impl->iceManager = iceManager;
470 impl->enableProfilerFunction(
this);
473 ARMARX_DEBUG <<
"call preOnInitComponent for all plugins...";
475 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
479 <<
") preOnInitComponent...";
480 plugin->preOnInitComponent();
482 <<
") preOnInitComponent...done!";
486 BOOST_CURRENT_FUNCTION);
487 ARMARX_DEBUG <<
"call preOnInitComponent for all plugins...done!";
502 ARMARX_DEBUG <<
"call postOnInitComponent for all plugins...";
504 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
508 <<
") postOnInitComponent...";
509 plugin->postOnInitComponent();
511 <<
") postOnInitComponent...done!";
515 BOOST_CURRENT_FUNCTION);
516 ARMARX_DEBUG <<
"call postOnInitComponent for all plugins...done!";
519 setObjectState(eManagedIceObjectInitialized);
527 this->impl->proxy = proxy;
528 this->impl->objectAdapter = objectAdapter;
531 setObjectState(eManagedIceObjectStarting);
534 ARMARX_DEBUG <<
"call preOnConnectComponent for all plugins...";
536 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
540 <<
") preOnConnectComponent...";
541 plugin->preOnConnectComponent();
543 <<
") preOnConnectComponent...done!";
547 BOOST_CURRENT_FUNCTION);
548 ARMARX_DEBUG <<
"call preOnConnectComponent for all plugins...done!";
564 ARMARX_DEBUG <<
"call postOnConnectComponent for all plugins...";
566 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
570 <<
") postOnConnectComponent...";
571 plugin->postOnConnectComponent();
573 <<
") postOnConnectComponent...done!";
577 BOOST_CURRENT_FUNCTION);
578 ARMARX_DEBUG <<
"call postOnConnectComponent for all plugins...done!";
581 setObjectState(eManagedIceObjectStarted);
585 ManagedIceObject::disconnect()
593 ARMARX_DEBUG <<
"call preOnDisconnectComponent for all plugins...";
595 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
599 <<
") preOnDisconnectComponent...";
600 plugin->preOnDisconnectComponent();
602 <<
") preOnDisconnectComponent...done!";
606 BOOST_CURRENT_FUNCTION);
607 ARMARX_DEBUG <<
"call preOnDisconnectComponent for all plugins...done!";
612 ARMARX_DEBUG <<
"call preOnDisconnectComponent...done!";
620 ARMARX_DEBUG <<
"call postOnDisconnectComponent...done!";
622 ARMARX_DEBUG <<
"call postOnDisconnectComponent for all plugins...";
624 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
628 <<
") postOnDisconnectComponent...";
629 plugin->postOnDisconnectComponent();
631 <<
") postOnDisconnectComponent...done!";
635 BOOST_CURRENT_FUNCTION);
636 ARMARX_DEBUG <<
"call postOnDisconnectComponent for all plugins...done!";
643 setObjectState(eManagedIceObjectInitialized);
647 ManagedIceObject::exit()
651 setObjectState(eManagedIceObjectExiting);
665 catch (Ice::ObjectAdapterDeactivatedException&)
668 catch (Ice::NotRegisteredException&)
675 ARMARX_DEBUG <<
"call preOnExitComponent for all plugins...";
677 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
681 <<
") preOnExitComponent...";
682 plugin->preOnExitComponent();
684 <<
") preOnExitComponent...done!";
688 BOOST_CURRENT_FUNCTION);
689 ARMARX_DEBUG <<
"call preOnExitComponent for all plugins...done!";
704 ARMARX_DEBUG <<
"call postOnExitComponent for all plugins...";
706 [&](
const auto& typeidx,
const auto& name,
const auto& plugin)
710 <<
") postOnExitComponent...";
711 plugin->postOnExitComponent();
713 <<
") postOnExitComponent...done!";
717 BOOST_CURRENT_FUNCTION);
718 ARMARX_DEBUG <<
"call postOnExitComponent for all plugins...done!";
725 setObjectState(eManagedIceObjectExited);
726 impl->armarXManager =
nullptr;
727 impl->iceManager =
nullptr;
728 impl->objectScheduler =
nullptr;
729 impl->objectAdapter =
nullptr;
730 impl->proxy =
nullptr;
735 ManagedIceObject::setObjectState(
int newState)
738 std::unique_lock lock(impl->objectStateMutex);
739 ARMARX_DEBUG <<
"setObjectState: " << impl->objectState <<
" -> " << newState;
741 if (newState == impl->objectState)
746 impl->objectState = (ManagedIceObjectState)newState;
747 impl->stateCondition.notify_all();
760 object->offeringTopic(armarx::Profiler::PROFILER_TOPIC_NAME);
761 ProfilerListenerPrx profilerTopic =
object->getIceManager()->getTopic<ProfilerListenerPrx>(
762 armarx::Profiler::PROFILER_TOPIC_NAME);
764 object->impl->profiler->setLoggingStrategy(strategy);
765 ARMARX_INFO_S <<
"Profiler enabled for " <<
object->getName();
771 std::unique_lock lock(impl->objectStateMutex);
772 return impl->objectState;
778 return impl->objectScheduler;
781 ManagedIceObjectConnectivity
784 std::unique_lock lock(impl->connectivityMutex);
785 return impl->connectivity;
797 std::unique_lock lock(impl->metaInfoMapMutex);
798 impl->metaInfoMap[id] = value;
804 std::unique_lock lock(impl->metaInfoMapMutex);
805 return impl->metaInfoMap[id];
811 std::unique_lock lock(impl->metaInfoMapMutex);
812 return impl->metaInfoMap;
817 std::function<
void(
void)> f,
819 bool assureMeanInterval,
820 bool forceSystemTime)
824 <<
"The name '" << uniqueName <<
"' is not unique!";
825 impl->periodicTasks[uniqueName] =
833 if (!impl->periodicTasks.count(name))
837 const auto task = impl->periodicTasks.at(name);
840 impl->periodicTasks.erase(name);
848 if (impl->periodicTasks.count(name))
850 return impl->periodicTasks.at(name);
856 armarx::ManagedIceObject::foreach_plugin(
860 const char* function)
863 ARMARX_DEBUG <<
"foreach_plugin called from " << file <<
':' << line <<
" in function '"
865 std::set<ManagedIceObjectPlugin*> processed;
866 std::map<ManagedIceObjectPlugin*, std::tuple<std::type_index, std::string>> toProcess;
867 for (
const auto& [key, plugin] : _plugins)
869 const auto& [typeidx, name] = key;
871 << plugin.get() <<
") to process list";
873 toProcess.emplace(plugin.get(), key);
876 while (processed.size() < toProcess.size())
879 const std::size_t oldNumProcessed = processed.size();
881 << toProcess.size() - oldNumProcessed <<
" plugins";
882 for (
const auto& [plugin, key] : toProcess)
884 if (processed.count(plugin))
888 const auto& [typeidx, name] = key;
890 <<
", @" << plugin <<
"): checking";
891 bool blocked =
false;
892 for (
const auto dep : plugin->_dependsOn)
894 if (!processed.count(dep))
903 <<
", @" << plugin <<
"): skipping for now";
908 <<
", @" << plugin <<
"): run functor";
909 f(typeidx, name, plugin);
910 processed.emplace(plugin);
912 if (processed.size() == oldNumProcessed)
914 std::stringstream
str;
915 str <<
"plugin graph is no DAG!\n";
916 for (
const auto& [plugin, key] : toProcess)
918 const auto& [typeidx, name] = key;
921 if (plugin->_dependsOn.empty())
923 str <<
" has no dependencies\n";
927 for (
const auto dep : plugin->_dependsOn)
929 str <<
" depends on " << dep <<
'\n';
The ManagedIceObject is the base class for all ArmarX objects.
ManagedIceObjectConnectivity getConnectivity() const
Retrieve connectivity of the object (topcis as well as proxies)
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
VariantBasePtr getMetaInfo(const std::string &id)
virtual void preOnInitComponent()
Profiler::ProfilerPtr getProfiler() const
getProfiler returns an instance of armarx::Profiler
bool unsubscribeFromTopic(const std::string &name)
Unsubscribe from a topic.
bool stopPeriodicTask(const std::string &name)
IceUtil::Handle< SimplePeriodicTask< std::function< void(void)> > > PeriodicTaskPtr
virtual void onExitComponent()
Hook for subclass.
StringVariantBaseMap getMetaInfoMap() const
static const ManagedIceObjectPtr NullPtr
A nullptr to be used when a const ref to a nullptr is required.
static std::string generateSubObjectName(const std::string &superObjectName, const std::string &subObjectName)
Generates a unique name for a sub object from a general name and unique name.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void waitForObjectScheduler()
Waits until the ObjectScheduler could resolve all dependencies.
ArmarXObjectSchedulerPtr getObjectScheduler() const
virtual void postOnExitComponent()
Ice::ObjectAdapterPtr getObjectAdapter() const
Returns object's Ice adapter.
virtual void postOnInitComponent()
virtual void onDisconnectComponent()
Hook for subclass.
~ManagedIceObject() override
ManagedIceObject(ManagedIceObject const &other)
virtual std::string getDefaultName() const =0
Retrieve default name of component.
virtual void postOnDisconnectComponent()
void terminate()
Initiates termination of this IceManagedObject.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
void waitForProxy(std::string const &name, bool addToDependencies)
std::unique_ptr< ManagedIceObjectPlugin > & getPluginPointer(std::type_info const &type, std::string const &prefix)
ManagedIceObject()
Protected default constructor.
virtual void onConnectComponent()=0
Pure virtual hook for the subclass.
std::string getName() const
Retrieve name of object.
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
bool removeProxyDependency(const std::string &name)
This function removes the dependency of this object on the in parameter name specified object.
Ice::CommunicatorPtr getCommunicator() const
void startPeriodicTask(const std::string &uniqueName, std::function< void(void)> f, int periodMs, bool assureMeanInterval=false, bool forceSystemTime=true)
virtual void preOnConnectComponent()
virtual void preOnDisconnectComponent()
static std::string GetObjectStateAsString(int state)
virtual void onInitComponent()=0
Pure virtual hook for the subclass.
int getState() const
Retrieve current state of the ManagedIceObject.
PeriodicTaskPtr getPeriodicTask(const std::string &name)
void setMetaInfo(const std::string &id, const VariantBasePtr &value)
Allows to set meta information that can be queried live via Ice interface on the ArmarXManager.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
void preambleGetTopic(std::string const &name)
void setName(std::string name)
Override name of well-known object.
virtual void preOnExitComponent()
virtual void postOnConnectComponent()
std::vector< std::string > getUnresolvedDependencies() const
returns the names of all unresolved dependencies
void enableProfiler(bool enable)
setProfiler allows setting ManagedIceObject::profiler to a new instance (if the new instance is actua...
The armarx::Profiler::Profiler class can be used for timing executions within the ArmarX framework.
The ProxyDependency class is part of the ManagedIceObjectConnectivity.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
static int USleep(long usec)
like timed_wait on boost condition_variables, but with timeserver support
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_VERBOSE
The logging level for verbose information.
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
::IceInternal::ProxyHandle<::IceProxy::IceStorm::Topic > TopicPrx
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
::IceInternal::Handle<::Ice::ObjectAdapter > ObjectAdapterPtr
std::shared_ptr< LoggingStrategy > LoggingStrategyPtr
std::shared_ptr< Profiler > ProfilerPtr
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< ManagedIceObjectDependency > ManagedIceObjectDependencyPtr
IceUtil::Handle< ArmarXManager > ArmarXManagerPtr
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceUtil::Handle< ArmarXObjectScheduler > ArmarXObjectSchedulerPtr
std::string GetTypeString(const std::type_info &tinf, bool withoutNamespaceSpecifier=false)
IceUtil::Handle< IceManager > IceManagerPtr
IceManager smart pointer.
SimplePeriodicTask(Ts...) -> SimplePeriodicTask< std::function< void(void)> >
::IceInternal::Handle<::armarx::VariantBase > VariantBasePtr
IceInternal::Handle< ManagedIceObject > ManagedIceObjectPtr