iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParameterImpl.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_PARAMETERIMPL_H
37 #define INCLUDE_NRT_CORE_MODEL_DETAILS_PARAMETERIMPL_H
38 
40 
41 // ######################################################################
42 inline nrt::Component *
44 { return dynamic_cast<nrt::Component *>(this); }
45 
46 // ######################################################################
47 inline nrt::Component const *
49 { return dynamic_cast<nrt::Component const *>(this); }
50 
51 // ######################################################################
52 template <typename T> inline
54  nrt::ParameterBase(), itsCallback(), itsVal(def.defaultValue()), itsDef(def)
55 { }
56 
57 // ######################################################################
58 template <typename T> inline
60 {
61  // Get a unique lock into our mutex, to ensure all get(), callbacks, etc are done before we die:
62  itsMutex.lock(); // keep us locked up into oblivion, base destructor will unlock at the last moment
63 }
64 
65 // ######################################################################
66 template <typename T> inline
67 std::string const & nrt::ParameterCore<T>::name() const
68 { return itsDef.name(); }
69 
70 // ######################################################################
71 template <typename T> inline
73 {
74  boost::shared_lock<boost::shared_mutex> lck(itsMutex);
75 
76  // If we have a checker port, then issue a check. Note that if check() returns something, the policy here is to just
77  // use that thing but not update our internal value (calling set()) as this poses locking, const-correctness,
78  // posting, and other problems:
79  /*
80  if (itsChecker)
81  {
82  auto res = itsChecker->check(nrt::MessageCheckerPolicy::Any);
83  try { while (res.exhausted() == false) if (auto msg = res.get()) { return msg->value(); } }
84  catch (...) { } // just swallow exceptions here
85  }
86  */
87  return itsVal;
88 }
89 
90 // ######################################################################
91 template <typename T> inline
92 void nrt::ParameterCore<T>::setCallback(std::function<void(T const &)> cb)
93 {
94  boost::unique_lock<boost::shared_mutex> lck(itsMutex);
95 
96  itsCallback = cb;
97 }
98 
99 // ######################################################################
100 template <typename T> inline
101 void nrt::ParameterCore<T>::set(T const & newVal)
102 {
103  boost::upgrade_lock<boost::shared_mutex> lck(itsMutex);
104 
105  // Do we allow online changes, if running?
106  if (owner() && owner()->running() &&
108  throw nrt::exception::
109  ParameterException(nrt::exception::ParameterException::NoOnlineChanges, this, "Parameter does not accept "
110  "online changes, you need to stop your model before attempting to set the parameter");
111 
112  // Is the value authorized, depending on the type of valid values we have:
113  if (itsDef.itsValidValuesSpec->checkValueValidity(newVal) == false)
114  {
115  // ooops, given value is not valid, let's throw:
116  std::ostringstream os;
117  os << "Provided value [" << newVal << "] not valid according to specification " << itsDef.itsValidValuesSpec->str();
118 
119  throw nrt::exception::ParameterException(nrt::exception::ParameterException::InvalidValue, this, os.str());
120  }
121 
122  // If we have a callback, see whether it likes this change:
123  if (itsCallback)
124  {
125  try { itsCallback(newVal); }
126  catch (nrt::exception::BadParameter const & e)
127  {
128  // Even though the change did not go through, we still send a notify of param changed; this will put back the
129  // current value into the GUI field in NRT designer (undoing the user edits):
130  if (owner() && owner()->initialized()) owner()->notifyParamChanged(nrt::ParameterState::Update, this);
131 
132  std::ostringstream os;
133  os << "Provided value [" << newVal << "] rejected by callback with reason [" << e.what() << ']';
134  throw nrt::exception::
135  ParameterException(nrt::exception::ParameterException::ValueRejectedByCallback, this, os.str());
136  }
137  }
138 
139  // If we made it through, all is ok. Change the value:
140  {
141  boost::upgrade_to_unique_lock<boost::shared_mutex> ulock(lck);
142  itsVal = newVal;
143  }
144 
145  // Notify the owner that the param was changed:
146  if (owner() && owner()->initialized()) owner()->notifyParamChanged(nrt::ParameterState::Update, this);
147 
148  // If we have a poster, post the new value:
149  /**
150  if (itsPoster)
151  {
152  std::shared_ptr<nrt::Message<T> > msg(new nrt::Message<T>(newVal));
153  itsPoster->doPost(msg);
154  }
155  */
156 }
157 
158 // ######################################################################
159 template <typename T> inline
160 void nrt::ParameterCore<T>::strset(std::string const & valstring)
161 { nrt::ParameterCore<T>::set(nrt::detail::paramValFromString<T>(valstring, this)); }
162 
163 // ######################################################################
164 template <typename T> inline
165 std::string const nrt::ParameterCore<T>::strget() const
166 { return nrt::detail::paramStringFromVal(nrt::ParameterCore<T>::get(), this); }
167 
168 // ######################################################################
169 template <typename T> inline
171 {
173 
174  boost::shared_lock<boost::shared_mutex> lck(itsMutex);
175 
176  // Build the descriptor
177  Component const * parent = owner();
178  if (parent) ps.descriptor = parent->descriptor() + ':' + itsDef.name();
179  else ps.descriptor = itsDef.name();
180 
181  // Populate the other fields:
182  ps.name = itsDef.name();
183  ps.description = itsDef.description();
184  ps.valuetype = nrt::demangledName<T>();
185  ps.defaultvalue = itsDef.defaultValueString();
186  ps.value = strget();
187  ps.validvalues = itsDef.validValuesString();
188  ps.flags = itsDef.flags();
189  ps.category = itsDef.category().name;
190  ps.categorydescription = itsDef.category().description;
191 
192  return ps;
193 }
194 
195 /*
196 // ######################################################################
197 template <typename T> inline
198 void nrt::ParameterCore<T>::createPort(ModuleParamPort const ptype, std::string const & module,
199  std::string const & descriptor)
200 {
201  boost::shared_lock<boost::shared_mutex> lck(itsMutex);
202 
203  switch(ptype)
204  {
205  case nrt::ModuleParamPort::Poster:
206  itsPoster.reset(); // make sure we first properly destroy and un-register any previously created port
207  itsPoster.reset(new nrt::MessagePosterCore<nrt::ParameterPosting<T> >
208  (module, descriptor, "Poster for Parameter "+itsDef.name()));
209  break;
210 
211  case nrt::ModuleParamPort::Checker:
212  itsChecker.reset(); // make sure we first properly destroy and un-register any previously created port
213  itsChecker.reset(new nrt::MessageCheckerCore<nrt::ParameterChecking<T> >
214  (module, descriptor, "Checker for Parameter "+itsDef.name()));
215  break;
216 
217  case nrt::ModuleParamPort::Subscriber:
218  itsSubscriber.reset(); // make sure we first properly destroy and un-register any previously created port
219  itsSubscriber.reset(new nrt::ParameterMessageSubscriber<T>
220  (this, module, descriptor, "Subscriber for Parameter "+itsDef.name()));
221  break;
222  }
223 }
224 
225 // ######################################################################
226 template <typename T> inline
227 void nrt::ParameterCore<T>::deletePort(ModuleParamPort const ptype)
228 {
229  boost::shared_lock<boost::shared_mutex> lck(itsMutex);
230 
231  switch(ptype)
232  {
233  case nrt::ModuleParamPort::Poster: itsPoster.reset(); break;
234  case nrt::ModuleParamPort::Checker: itsChecker.reset(); break;
235  case nrt::ModuleParamPort::Subscriber: itsSubscriber.reset(); break;
236  }
237 }
238 
239 // ######################################################################
240 template <typename T> inline
241 void nrt::ParameterCore<T>::setPosterTopicP(std::string const & topic)
242 {
243  if (itsPoster) itsPoster->setTopic(topic);
244  else throw nrt::exception::ParameterException(nrt::exception::ParameterException::InvalidValue, this,
245  "Must create Poster port before setting topic");
246 }
247 
248 // ######################################################################
249 template <typename T> inline
250 void nrt::ParameterCore<T>::setCheckerTopicFilterP(std::string const & topicfilt)
251 {
252  if (itsChecker) itsChecker->setTopicFilter(topicfilt);
253  else throw nrt::exception::ParameterException(nrt::exception::ParameterException::InvalidValue, this,
254  "Must create Checker port before setting topic filter");
255 }
256 
257 // ######################################################################
258 template <typename T> inline
259 void nrt::ParameterCore<T>::setSubscriberTopicFilterP(std::string const & topicfilt)
260 {
261  if (itsSubscriber) itsSubscriber->setTopicFilter(topicfilt);
262  else throw nrt::exception::ParameterException(nrt::exception::ParameterException::InvalidValue, this,
263  "Must create Subscriber port before setting topic filter");
264 }
265 */
266 // ######################################################################
267 template <typename T> inline
269 {
270  itsVal = def.defaultValue();
271  *(const_cast<nrt::ParameterDef<T> *>(& itsDef)) = def;
272 }
273 /*
274 // ######################################################################
275 template <typename T> inline
276 nrt::ParameterMessageSubscriber<T>::
277 ParameterMessageSubscriber(nrt::ParameterCore<T> * param, std::string const & mod, std::string const & portna,
278  std::string const & descr) :
279  nrt::MessageSubscriberCore<nrt::ParameterSubscription<T> >(mod, portna, descr), itsParam(param)
280 { }
281 
282 // ######################################################################
283 template <typename T> inline
284 nrt::ParameterMessageSubscriber<T>::~ParameterMessageSubscriber()
285 { }
286 
287 // ######################################################################
288 template <typename T> inline
289 void nrt::ParameterMessageSubscriber<T>::onMessage(nrt::ParameterMessageSubscriber<T>::InPtr msg)
290 { itsParam->set(msg->value()); }
291 */
292 #endif // INCLUDE_NRT_CORE_MODEL_DETAILS_PARAMETERIMPL_H
293