JeVois  1.0
JeVois Smart Embedded Machine Vision Toolkit
ComponentImpl.H
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 // This code is inspired by the Neuromorphic Robotics Toolkit (http://nrtkit.org)
19 
20 #pragma once
21 
22 #include <jevois/Util/Demangle.H>
23 #include <jevois/Debug/Log.H>
24 
25 // ######################################################################
26 // ######################################################################
27 // ######################################################################
28 template <class Comp, typename... Args> inline
29 std::shared_ptr<Comp> jevois::Component::addSubComponent(std::string const & instance, Args && ...args)
30 {
31  JEVOIS_TRACE(5);
32 
33  // Enforce that Comp derives from Component:
34  static_assert(std::is_base_of<jevois::Component, Comp>::value, "Comp must derive from jevois::Component");
35 
36  std::shared_ptr<Comp> subComp;
37  {
38  // Lock up so we guarantee the instance name does not get robbed as we add the sub:
39  boost::unique_lock<boost::shared_mutex> ulck(itsSubMtx);
40 
41  // Create the sub and put it into a shared_ptr. Note: computeInstanceName() will throw if name clashes with some
42  // existing sub-component:
43  subComp.reset(new Comp(computeInstanceName(instance, jevois::demangledName<Comp>()), std::forward<Args>(args)...));
44 
45  // Then add it as a sub-component to us, if there is not instance name clash with our other sub-components:
46  LDEBUG("Adding SubComponent [" << jevois::demangledName<Comp>() << ":: " << instance << ']');
47  itsSubComponents.push_back(subComp);
48  subComp->itsParent = this;
49 
50  // By default, inherit the path from the parent:
51  subComp->setPath(absolutePath());
52  }
53 
54  // Finally bring it to our runstate:
55  if (itsInitialized) subComp->init();
56 
57  return subComp;
58 }
59 
60 // ######################################################################
61 template <class Comp> inline
62 std::shared_ptr<Comp> jevois::Component::getSubComponent(std::string const & instance) const
63 {
64  JEVOIS_TRACE(6);
65 
66  // Enforce that Comp derives from Component:
67  static_assert(std::is_base_of<jevois::Component, Comp>::value, "Comp must derive from jevois::Component");
68 
69  boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
70 
71  for (std::shared_ptr<jevois::Component> c : itsSubComponents)
72  if (c->instanceName() == instance)
73  {
74  std::shared_ptr<Comp> ret = std::dynamic_pointer_cast<Comp>(c);
75  if (ret) return ret; // correct type
76  LFATAL("SubComponent [" << instance << "] is not of type [" << jevois::demangledName<Comp>() << ']');
77  }
78 
79  LFATAL("SubComponent [" << instance << "] not found");
80 }
81 
82 // ######################################################################
83 // Specialization for jevois::Component return: no need to cast
84 namespace jevois
85 {
86  template <> inline
87  std::shared_ptr<Component> Component::getSubComponent<Component>(std::string const & instance) const
88  {
89  ///JEVOIS_TRACE(6);
90 
91  boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
92 
93  for (std::shared_ptr<Component> c : itsSubComponents)
94  if (c->instanceName() == instance) return c;
95 
96  LFATAL("SubComponent [" << instance << "] not found");
97  }
98 }
99 
100 // ######################################################################
101 template <class Comp>
102 void jevois::Component::removeSubComponent(std::shared_ptr<Comp> & component)
103 {
104  JEVOIS_TRACE(5);
105 
106  static_assert(std::is_base_of<jevois::Component, Comp>::value, "Comp must derive from jevois::Component");
107 
108  boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
109 
110  for (auto itr = itsSubComponents.begin(); itr != itsSubComponents.end(); ++itr)
111  if (itr->get() == component.get())
112  {
113  // First, nuke the "component" shared_ptr so it does not show up as a dangling shared_ptr in
114  // doRemoveSubComponent(). itr still has one ref to the pointee:
115  component.reset();
116 
117  // Then remove that sub:
118  doRemoveSubComponent(itr, uplck, "SubComponent");
119  return;
120  }
121 
122  LERROR("SubComponent [" << component->instanceName() << "] not found. Ignored.");
123 }
124 
125 
126 // ######################################################################
127 template <typename T> inline
128 std::vector<std::string>
129 jevois::Component::setParamVal(std::string const & descriptor, T const & val)
130 {
131  JEVOIS_TRACE(7);
132 
133  std::vector<std::string> ret;
134  findParamAndActOnIt(descriptor,
135 
136  [&ret,&val](jevois::ParameterBase * param, std::string const & unrolled)
137  {
138  jevois::ParameterCore<T> * p = dynamic_cast<jevois::ParameterCore<T> *>(param);
139  if (p == nullptr) throw std::range_error("Attempted to set Parameter [" + unrolled +
140  "] with value of incorrect type");
141  p->set(val);
142  ret.push_back(unrolled);
143  },
144 
145  [&ret]() { return ret.empty(); }
146  );
147  return ret;
148 }
149 
150 // ######################################################################
151 template <typename T> inline
152 void jevois::Component::setParamValUnique(std::string const & descriptor, T const & val)
153 {
154  JEVOIS_TRACE(7);
155 
156  std::vector<std::string> ret = setParamVal(descriptor, val);
157  if (ret.size() > 1) throw std::range_error("Multiple matches for descriptor [" + descriptor +
158  "] while only one is allowed");
159 }
160 
161 // ######################################################################
162 template <typename T> inline
163 std::vector<std::pair<std::string, T> >
164 jevois::Component::getParamVal(std::string const & descriptor) const
165 {
166  JEVOIS_TRACE(8);
167 
168  std::vector<std::pair<std::string, T> > ret;
169  findParamAndActOnIt(descriptor,
170 
171  [&ret](jevois::ParameterBase * param, std::string const & unrolled)
172  {
173  jevois::ParameterCore<T> * p = dynamic_cast<jevois::ParameterCore<T> *>(param);
174  if (p == nullptr) throw std::range_error("Attempted to get Parameter [" + unrolled +
175  "] with value of incorrect type");
176  ret.push_back(std::make_pair(unrolled, p->get()));
177  },
178 
179  [&ret]() { return ret.empty(); }
180  );
181  return ret;
182 }
183 
184 // ######################################################################
185 template <typename T> inline
186 T jevois::Component::getParamValUnique(std::string const & descriptor) const
187 {
188  JEVOIS_TRACE(8);
189 
190  std::vector<std::pair<std::string, T> > ret = getParamVal<T>(descriptor);
191  if (ret.size() > 1) throw std::range_error("Multiple matches for descriptor [" + descriptor +
192  "] while only one is allowed");
193  return ret[0].second;
194 }
195 
196 // Include inlined implementation details that are of no interest to the end user
198 
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level. ...
Definition: Log.H:148
A changeable parameter for a Component, core class.
Definition: Parameter.H:153
std::vector< std::string > setParamVal(std::string const &paramdescriptor, T const &val)
Set a parameter value.
void setParamValUnique(std::string const &paramdescriptor, T const &val)
Set a parameter value, simple version assuming only one parameter match.
std::shared_ptr< Comp > addSubComponent(std::string const &instance, Args &&...args)
Pseudo-constructor: construct and add another component as a subcomponent of this one...
Definition: ComponentImpl.H:29
#define JEVOIS_TRACE(level)
Trace object.
Definition: Log.H:260
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level. ...
Definition: Log.H:186
T getParamValUnique(std::string const &paramdescriptor) const
Get a parameter value, simple version assuming only one parameter match.
T get() const
Get the value of this Parameter.
Definition: ParameterImpl.H:73
std::shared_ptr< Comp > getSubComponent(std::string const &instance) const
Get a sub-component by instance name.
Definition: ComponentImpl.H:62
void removeSubComponent(std::shared_ptr< Comp > &component)
Remove a sub-Component from this Component, by shared_ptr.
Base class for Parameter.
Definition: Parameter.H:91
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:205
void set(T const &newVal)
Set the value of this Parameter.
Definition: ParameterImpl.H:89
std::vector< std::pair< std::string, T > > getParamVal(std::string const &paramdescriptor) const
Get parameter(s) value(s) by descriptor.
std::string absolutePath(std::string const &path="")
If given path is relative (not starting with /), prepend the Component path to it.
Definition: Component.C:500