iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ComponentImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_MODEL_DETAILS_COMPONENTIMPL_H
37 #define INCLUDE_NRT_CORE_MODEL_DETAILS_COMPONENTIMPL_H
38 
40 #include <nrt/Core/Debugging/Log.H>
41 
42 // ######################################################################
43 // ######################################################################
44 // ######################################################################
46 {
47  // meta() should have const semantics, but we can't set the className in the constructor since the object is not fully
48  // built yet. This is one of the cases where const_cast is justified (as long as we ensure that itsMetaInfo.className
49  // will never be used directly except in the present function):
50  if (itsMetaInfo.className.empty())
51  const_cast<nrt::Component*>(this)->itsMetaInfo.className = nrt::demangle(typeid(*this).name());
52  return itsMetaInfo;
53 }
54 
55 // ######################################################################
57 { return (m.className == className && m.instanceName == instanceName); }
58 
59 // ######################################################################
60 inline nrt::Component::MetaInfo::MetaInfo(std::string const & instancename) : className(), instanceName(instancename)
61 { }
62 
63 // ######################################################################
64 inline std::string const nrt::Component::MetaInfo::str() const
65 {
66  if (instanceName.empty()) return className;
67  else return className + '-' + instanceName;
68 }
69 
70 // ######################################################################
71 // ######################################################################
72 // ######################################################################
73 template <class Comp> inline
74 std::shared_ptr<Comp> nrt::Component::addSubComponent(std::string const & instanceName)
75 {
76  // Keep this code in sync with module version
77 
78  // Enforce that Comp derives from Component, but not from Module:
79  static_assert(std::is_base_of<nrt::Component, Comp>::value, "Comp must derive from nrt::Component");
80  static_assert(!std::is_base_of<nrt::ModuleBase, Comp>::value, "Use nrt::Module::addSubModule() for objects "
81  "that derive from nrt::Module");
82 
83  // First, create the sub and put it into a shared_ptr:
84  std::shared_ptr<Comp> subComp(new Comp(computeInstanceName(instanceName)));
85 
86  // Then add it as a sub-component to us:
87  {
88  boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
89 
90  std::string const inst = subComp->meta().instanceName;
91 
92  for (std::shared_ptr<nrt::Component> const & c : itsSubComponents)
93  if (inst == c->meta().instanceName)
94  NRT_FATAL("Cannot add two subcomponents with identical instanceNames [" << inst << ']');
95 
96  NRT_MODDEBUG("Adding SubComponent [" << subComp->meta().str() << ']');
97 
98  {
99  boost::upgrade_to_unique_lock<boost::shared_mutex> ulck(uplck);
100  itsSubComponents.push_back(subComp);
101  subComp->itsParent = this;
102  }
103  }
104 
105  // Finally bring it to our runstate:
106  if (itsInitialized) subComp->init();
107  if (itsStarted) subComp->start();
108  if (itsRunning) subComp->launch();
109 
110  return subComp;
111 }
112 
113 // ######################################################################
114 template <class Comp> inline
115 std::shared_ptr<Comp> nrt::Component::getSubComponent(std::string const & instanceName) const
116 {
117  // Keep this code in sync with module version
118 
119  // Enforce that Comp derives from Component, but not from Module:
120  static_assert(std::is_base_of<nrt::Component, Comp>::value, "Comp must derive from nrt::Component");
121  static_assert( ! std::is_base_of<nrt::Module, Comp>::value, "Use nrt::Module::getSubModule() for objects "
122  "that derive from nrt::Module");
123 
124  boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
125 
126  for (std::shared_ptr<nrt::Component> c : itsSubComponents)
127  if (instanceName == c->meta().instanceName)
128  {
129  std::shared_ptr<Comp> ret = std::dynamic_pointer_cast<Comp>(c);
130  if (ret) return ret; // correct type
131  NRT_FATAL("SubComponent [" << instanceName << "] is not of type [" << nrt::demangledName<Comp>() << ']');
132  }
133 
134  NRT_FATAL("SubComponent [" << instanceName << "] not found");
135 }
136 
137 // ######################################################################
138 // Specialization for nrt::Component return: no need to cast
139 namespace nrt
140 {
141  template <> inline
142  std::shared_ptr<Component> Component::getSubComponent<Component>(std::string const & instanceName) const
143  {
144  boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
145 
146  for (std::shared_ptr<Component> c : itsSubComponents) if (instanceName == c->meta().instanceName) return c;
147 
148  NRT_FATAL("SubComponent [" << instanceName << "] not found");
149  }
150 }
151 
152 // ######################################################################
153 template <class Comp>
154 void nrt::Component::removeSubComponent(std::shared_ptr<Comp> & component)
155 {
156  // Keep this code in sync with module version
157 
158  static_assert(std::is_base_of<nrt::Component, Comp>::value, "Comp must derive from nrt::Component");
159  static_assert( ! std::is_base_of<nrt::Module, Comp>::value, "Use nrt::Module::removeSubModule() for objects "
160  "that derive from nrt::Module");
161 
162  boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
163 
164  for (auto itr = itsSubComponents.begin(); itr != itsSubComponents.end(); ++itr)
165  if (itr->get() == component.get())
166  {
167  if (component->initialized()) component->uninit();
168 
169  NRT_MODDEBUG("Removing SubComponent [" << component->meta().str() << ']');
170 
171  boost::upgrade_to_unique_lock<boost::shared_mutex> ulck(uplck);
172  component->prepareForDeletion();
173  itsSubComponents.erase(itr);
174 
175  if (component.use_count() > 1)
176  NRT_WARNING(component.use_count() - 1 << " additional external shared_ptr references exist to "
177  "Component [" << component->meta().str() << "]. Component was NOT deleted.");
178 
179  component.reset(); // nuke the shared_ptr, this should yield a delete unless use_count was > 1
180  return;
181  }
182 
183  NRT_WARNING("SubComponent [" << component->meta().str() << "] not found. Ignored.");
184 }
185 
186 
187 // ######################################################################
188 template <typename T> inline
189 std::vector<std::string>
190 nrt::Component::setParamVal(std::string const & descriptor, T const & val)
191 {
192  std::vector<std::string> ret;
193  findParamAndActOnIt(descriptor,
194 
195  [&ret,&val](nrt::ParameterBase * param, std::string const & unrolled)
196  {
197  nrt::ParameterCore<T> * p = dynamic_cast<nrt::ParameterCore<T> *>(param);
198  if (p == nullptr)
199  throw nrt::exception::ParameterException(nrt::exception::ParameterException::BadValueType,
200  nullptr, "Attempted to set Parameter [" + unrolled +
201  "] with value of incorrect type");
202  p->set(val);
203  ret.push_back(unrolled);
204  },
205 
206  [&ret]() { return ret.empty(); }
207  );
208  return ret;
209 }
210 
211 // ######################################################################
212 template <typename T> inline
213 void nrt::Component::setParamValUnique(std::string const & descriptor, T const & val)
214 {
215  std::vector<std::string> ret = setParamVal(descriptor, val);
216  if (ret.size() > 1) nrt::exception::ParameterException(nrt::exception::ParameterException::MultipleMatches, nullptr,
217  "Multiple matches for descriptor [" + descriptor +
218  "] while only one is allowed");
219 }
220 
221 // ######################################################################
222 template <typename T> inline
223 std::vector<std::pair<std::string, T> >
224 nrt::Component::getParamVal(std::string const & descriptor) const
225 {
226  std::vector<std::pair<std::string, T> > ret;
227  findParamAndActOnIt(descriptor,
228 
229  [&ret](nrt::ParameterBase * param, std::string const & unrolled)
230  {
231  nrt::ParameterCore<T> * p = dynamic_cast<nrt::ParameterCore<T> *>(param);
232  if (p == nullptr)
233  throw nrt::exception::ParameterException(nrt::exception::ParameterException::BadValueType,
234  nullptr, "Attempted to get Parameter [" + unrolled +
235  "] with value of incorrect type");
236  ret.push_back(std::make_pair(unrolled, p->get()));
237  },
238 
239  [&ret]() { return ret.empty(); }
240  );
241  return ret;
242 }
243 
244 // ######################################################################
245 template <typename T> inline
246 T nrt::Component::getParamValUnique(std::string const & descriptor) const
247 {
248  std::vector<std::pair<std::string, T> > ret = getParamVal<T>(descriptor);
249  if (ret.size() > 1) nrt::exception::ParameterException(nrt::exception::ParameterException::MultipleMatches, nullptr,
250  "Multiple matches for descriptor [" + descriptor +
251  "] while only one is allowed");
252  return ret[0].second;
253 }
254 
255 // Include inlined implementation details that are of no interest to the end user
256 //#include <nrt/Core/Blackboard/Module.H>
258 
259 #endif // INCLUDE_NRT_CORE_MODEL_DETAILS_COMPONENTIMPL_H