dynamic-graph  4.1.0-8-gdab7-dirty
Dynamic graph library
signal.t.cpp
1 // -*- mode: c++ -*-
2 // Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
3 // JRL, CNRS/AIST.
4 //
5 
6 #ifndef DYNAMIC_GRAPH_SIGNAL_T_CPP
7 #define DYNAMIC_GRAPH_SIGNAL_T_CPP
8 #include <dynamic-graph/signal-caster.h>
9 #include <dynamic-graph/signal.h>
10 
11 #undef VP_TEMPLATE_DEBUG_MODE
12 #define VP_TEMPLATE_DEBUG_MODE 0
13 #include <dynamic-graph/debug.h>
14 
15 #define __SIGNAL_INIT(name, Tcpy, Tref, TrefNC, mutex) \
16  SignalBase<Time>(name), signalType(SIGNAL_TYPE_DEFAULT), Tcopy1(Tcpy), \
17  Tcopy2(Tcpy), Tcopy(&Tcopy1), Treference(Tref), \
18  TreferenceNonConst(TrefNC), Tfunction(), \
19  keepReference(KEEP_REFERENCE_DEFAULT), providerMutex(mutex)
20 
21 namespace dynamicgraph {
22 
23 template <class T, class Time>
24 Signal<T, Time>::Signal(std::string name)
25  : __SIGNAL_INIT(name, T(), NULL, NULL, NULL) {
26  return;
27 }
28 
29 /* ------------------------------------------------------------------------ */
30 
31 template <class T, class Time>
32 void Signal<T, Time>::set(std::istringstream &stringValue) {
33  (*this) = signal_cast<T>(stringValue);
34 }
35 
36 template <class T, class Time>
37 void Signal<T, Time>::get(std::ostream &os) const {
38  signal_disp<T>(this->accessCopy(), os);
39 }
40 
41 template <class T, class Time>
42 void Signal<T, Time>::trace(std::ostream &os) const {
43  try {
44  signal_trace<T>(this->accessCopy(), os);
45  } catch DG_RETHROW catch (...) {
46  DG_THROW ExceptionSignal(ExceptionSignal::SET_IMPOSSIBLE,
47  "TRACE operation not possible with this signal. ",
48  "(bad cast while getting value from %s).",
49  SignalBase<Time>::getName().c_str());
50  }
51 }
52 
53 /* ------------------------------------------------------------------------ */
54 
55 template <class T, class Time> const T &Signal<T, Time>::setTcopy(const T &t) {
56  if (Tcopy == &Tcopy1) {
57  Tcopy2 = t;
58  copyInit = true;
59  Tcopy = &Tcopy2;
60  return Tcopy2;
61  } else {
62  Tcopy1 = t;
63  copyInit = true;
64  Tcopy = &Tcopy1;
65  return Tcopy1;
66  }
67 }
68 
69 template <class T, class Time> T &Signal<T, Time>::getTwork() {
70  if (Tcopy == &Tcopy1)
71  return Tcopy2;
72  else
73  return Tcopy1;
74 }
75 
76 template <class T, class Time> const T &Signal<T, Time>::getTwork() const {
77  if (Tcopy == &Tcopy1)
78  return Tcopy2;
79  else
80  return Tcopy1;
81 }
82 
83 template <class T, class Time> const T &Signal<T, Time>::switchTcopy() {
84  if (Tcopy == &Tcopy1) {
85  Tcopy = &Tcopy2;
86  return Tcopy2;
87  } else {
88  Tcopy = &Tcopy1;
89  return Tcopy1;
90  }
91 }
92 
93 template <class T, class Time> void Signal<T, Time>::setConstant(const T &t) {
94  signalType = CONSTANT;
95  setTcopy(t);
96  setReady();
97 }
98 
99 template <class T, class Time>
100 void Signal<T, Time>::setReference(const T *t, Mutex *mutexref) {
101  signalType = REFERENCE;
102  Treference = t;
103  providerMutex = mutexref;
104  copyInit = false;
105  setReady();
106 }
107 
108 template <class T, class Time>
109 void Signal<T, Time>::setReferenceNonConstant(T *t, Mutex *mutexref) {
110  signalType = REFERENCE_NON_CONST;
111  Treference = t;
112  TreferenceNonConst = t;
113  providerMutex = mutexref;
114  copyInit = false;
115  setReady();
116 }
117 
118 template <class T, class Time>
119 void Signal<T, Time>::setFunction(boost::function2<T &, T &, Time> t,
120  Mutex *mutexref) {
121  signalType = FUNCTION;
122  Tfunction = t;
123  providerMutex = mutexref;
124  copyInit = false;
125  setReady();
126 }
127 
128 template <class T, class Time> const T &Signal<T, Time>::accessCopy() const {
129  return *Tcopy;
130 }
131 
132 template <class T, class Time> const T &Signal<T, Time>::access(const Time &t) {
133  switch (signalType) {
134  case REFERENCE:
135  case REFERENCE_NON_CONST: {
136  if (NULL == providerMutex) {
137  copyInit = true;
138  signalTime = t;
139  return setTcopy(*Treference);
140  } else {
141  try {
142 #ifdef HAVE_LIBBOOST_THREAD
143  boost::try_mutex::scoped_try_lock lock(*providerMutex);
144 #endif
145  copyInit = true;
146  signalTime = t;
147  return setTcopy(*Treference);
148  } catch (const MutexError &) {
149  return accessCopy();
150  }
151  }
152 
153  break;
154  }
155 
156  case FUNCTION: {
157  if (NULL == providerMutex) {
158  signalTime = t;
159  Tfunction(getTwork(), t);
160  copyInit = true;
161  return switchTcopy();
162  } else {
163  try {
164 #ifdef HAVE_LIBBOOST_THREAD
165  boost::try_mutex::scoped_try_lock lock(*providerMutex);
166 #endif
167  signalTime = t;
168  Tfunction(getTwork(), t);
169  copyInit = true;
170  return switchTcopy();
171  } catch (const MutexError &) {
172  return accessCopy();
173  }
174  }
175  break;
176  }
177  case CONSTANT:
178  default:
179  if (this->getReady()) {
180  setReady(false);
181  this->setTime(t);
182  }
183  return accessCopy();
184  };
185 }
186 
187 template <class T, class Time>
188 Signal<T, Time> &Signal<T, Time>::operator=(const T &t) {
189  if (keepReference && (REFERENCE_NON_CONST == signalType) &&
190  (NULL != TreferenceNonConst)) {
191  if (NULL == providerMutex) {
192  setTcopy(t);
193  (*TreferenceNonConst) = t;
194  } else {
195  try {
196 #ifdef HAVE_LIBBOOST_THREAD
197  boost::try_mutex::scoped_try_lock lock(*providerMutex);
198 #endif
199  setTcopy(t);
200  (*TreferenceNonConst) = t;
201  } catch (const MutexError &) { /* TODO ERROR */
202  }
203  }
204  } else {
205  setConstant(t);
206  }
207  return *this;
208 }
209 
210 template <class T, class Time>
211 std::ostream &Signal<T, Time>::display(std::ostream &os) const {
212  os << "Sig:" << this->name << " (Type ";
213  switch (this->signalType) {
214  case Signal<T, Time>::CONSTANT:
215  os << "Cst";
216  break;
217  case Signal<T, Time>::REFERENCE:
218  os << "Ref";
219  break;
220  case Signal<T, Time>::REFERENCE_NON_CONST:
221  os << "RefNonCst";
222  break;
223  case Signal<T, Time>::FUNCTION:
224  os << "Fun";
225  break;
226  }
227  return os << ")";
228 }
229 
230 } // end of namespace dynamicgraph.
231 
232 #undef __SIGNAL_INIT
233 #endif