OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WFlag.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WFLAG_H
26 #define WFLAG_H
27 
28 #include <boost/shared_ptr.hpp>
29 
30 #include "WCondition.h"
31 
32 /**
33  * Class to have a simple notification/condition system for simple flags. This is somewhat similar to the observer design pattern.
34  * The type of the flag is specified by the template parameter. Per default, it is of type bool.
35  */
36 template < typename T >
37 class WFlag
38 {
39 public:
40  /**
41  * The type for later access.
42  */
43  typedef T ValueType;
44 
45  /**
46  * Convenience typedef for a boost::shared_ptr.
47  */
48  typedef boost::shared_ptr< WFlag< T > > SPtr;
49 
50  /**
51  * Convenience typedef for a boost::shared_ptr. Const.
52  */
53  typedef boost::shared_ptr< const WFlag< T > > ConstSPtr;
54 
55  /**
56  * Constructor. Uses a given condition to realize the wait/notify functionality. By using this constructor, the specified
57  * condition gets deleted whenever this WFlag is deleted.
58  *
59  * \param condition the condition to use.
60  * \note condition can also be a WConditionOneShot.
61  * \param initial the initial value of this flag.
62  */
63  WFlag( WCondition* condition, T initial );
64 
65  /**
66  * Constructor. Uses a given condition to realize the wait/notify functionality. By using this constructor, the specified
67  * condition gets NOT explicitely deleted when this WFlag gets deleted.
68  *
69  * \param condition the condition to use.
70  * \note condition can also be a WConditionOneShot.
71  * \param initial the initial value of this flag.
72  */
73  WFlag( boost::shared_ptr< WCondition > condition, T initial );
74 
75  /**
76  * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
77  * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
78  * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because
79  * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original flag is changed
80  * (which after cloning is completely decoupled from the clone).
81  *
82  * \param from the instance to copy.
83  */
84  explicit WFlag( const WFlag& from );
85 
86  /**
87  * Destructor. It deletes the instance of WCondition specified on construction.
88  */
89  virtual ~WFlag();
90 
91  /**
92  * Operator returns value of the flag.
93  *
94  * \param resetChangeState when true, the changed() flag gets reset to false.
95  *
96  * \return the value.
97  */
98  virtual const T get( bool resetChangeState = false );
99 
100  /**
101  * Operator returns value of the flag.
102  *
103  * \return the value.
104  */
105  virtual const T get() const;
106 
107  /**
108  * Operator returns value of the flag.
109  *
110  * \return the value.
111  */
112  virtual const T operator()() const;
113 
114  /**
115  * Operator returns value of the flag. It does not reset the change flag.
116  *
117  * \return the value.
118  */
119  virtual operator T() const;
120 
121  /**
122  * Wait for the flag to change its value. For WConditionOneShot is also recognizes if the flag has changed before.
123  */
124  virtual void wait() const;
125 
126  /**
127  * Sets the new value for this flag. Also notifies waiting threads. After setting a value, changed() will be true.
128  *
129  * \param value the new value
130  * \param suppressNotification true to avoid a firing condition. This is useful for resetting values.
131  *
132  * \return true if the value has been set successfully.
133  *
134  * \note set( get() ) == true
135  */
136  virtual bool set( T value, bool suppressNotification = false );
137 
138  /**
139  * Sets the new value for this flag. Also notifies waiting threads.
140  *
141  * \param value the new value
142  */
143  virtual void operator()( T value );
144 
145  /**
146  * Returns the condition that is used by this flag.
147  *
148  * \return the condition
149  */
150  boost::shared_ptr< WCondition > getCondition();
151 
152  /**
153  * Returns the condition denoting a value change. In contrast to getCondition, this condition fires regardless of notification is suppressed
154  * during set() or not.
155  *
156  * \return the condition denoting a value change.
157  */
158  boost::shared_ptr< WCondition > getValueChangeCondition();
159 
160  /**
161  * Determines whether the specified value is acceptable. In WFlags, this always returns true. To modify the behaviour,
162  * implement this function in an appropriate way.
163  *
164  * \param newValue the new value.
165  *
166  * \return true if it is a valid/acceptable value.
167  */
168  virtual bool accept( T newValue );
169 
170  /**
171  * Tests whether a flag is currently valid. It is equal to accept( get() );
172  *
173  * \return true if current value is valid.
174  */
175  virtual bool isValid();
176 
177  /**
178  * True whenever the value inside this flag has changed since the last reset. It stays true until get( true ) is called or the reset value is
179  * true.
180  *
181  * \param reset if true, the change flag gets reset.
182  *
183  * \return true when the value has changed and not yet been reseted.
184  */
185  virtual bool changed( bool reset = false );
186 
187 protected:
188 
189  /**
190  * The condition to be used for waiting/notifying. Please note, that it gets deleted during destruction.
191  */
192  boost::shared_ptr< WCondition > m_condition;
193 
194  /**
195  * This condition is fired whenever the value changes. In contrast to m_condition, this also fires if set() is called with
196  * suppressNotification=true.
197  */
198  boost::shared_ptr< WCondition > m_valueChangeCondition;
199 
200  /**
201  * The flag value.
202  */
204 
205  /**
206  * Denotes whether the value has changed since the last reset.
207  */
208  bool m_changed;
209 
210 private:
211 };
212 
213 /**
214  * Alias for easy usage of WFLag< bool >.
215  */
216 typedef WFlag< bool > WBoolFlag;
217 
218 template < typename T >
219 WFlag< T >::WFlag( WCondition* condition, T initial ):
220  m_condition( boost::shared_ptr< WCondition >( condition ) ),
221  m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
222  m_flag( initial ),
223  m_changed( true )
224 {
225 }
226 
227 template < typename T >
228 WFlag< T >::WFlag( boost::shared_ptr< WCondition > condition, T initial ):
229  m_condition( condition ),
230  m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
231  m_flag( initial ),
232  m_changed( true )
233 {
234 }
235 
236 template < typename T >
237 WFlag< T >::WFlag( const WFlag& from ):
238  m_condition( boost::shared_ptr< WCondition >( new WCondition() ) ),
239  m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
240  m_flag( from.m_flag ),
241  m_changed( from.m_changed )
242 {
243 }
244 
245 template < typename T >
247 {
248 }
249 
250 template < typename T >
251 const T WFlag< T >::operator()() const
252 {
253  return get();
254 }
255 
256 template < typename T >
257 const T WFlag< T >::get( bool resetChangeState )
258 {
259  if( resetChangeState )
260  {
261  m_changed = false;
262  }
263  return m_flag;
264 }
265 
266 template < typename T >
267 const T WFlag< T >::get() const
268 {
269  return m_flag;
270 }
271 
272 template < typename T >
274 {
275  return get();
276 }
277 
278 template < typename T >
279 void WFlag< T >::wait() const
280 {
281  m_condition->wait();
282 }
283 
284 template < typename T >
285 void WFlag< T >::operator()( T value )
286 {
287  set( value );
288 }
289 
290 template < typename T >
291 bool WFlag< T >::set( T value, bool suppressNotification )
292 {
293  // if the value is the same as the current one -> do not notify but let the caller know "all ok"
294  if( m_flag == value )
295  {
296  return true;
297  }
298 
299  // let the caller know whether the value was acceptable.
300  if( !accept( value ) )
301  {
302  return false;
303  }
304 
305  m_flag = value;
306  m_changed = true;
307 
308  // is the notification suppressed ?
309  if( !suppressNotification )
310  {
311  m_condition->notify();
312  }
313  m_valueChangeCondition->notify();
314 
315  return true;
316 }
317 
318 template < typename T >
319 boost::shared_ptr< WCondition > WFlag< T >::getCondition()
320 {
321  return m_condition;
322 }
323 
324 template < typename T >
325 boost::shared_ptr< WCondition > WFlag< T >::getValueChangeCondition()
326 {
327  return m_valueChangeCondition;
328 }
329 
330 template < typename T >
331 bool WFlag< T >::accept( T /* newValue */ )
332 {
333  // please implement this method in your class to modify the behaviour.
334  return true;
335 }
336 
337 template < typename T >
339 {
340  return accept( get() );
341 }
342 
343 template < typename T >
344 bool WFlag< T >::changed( bool reset )
345 {
346  bool tmp = m_changed;
347  if( reset )
348  {
349  m_changed = false;
350  }
351  return tmp;
352 }
353 
354 #endif // WFLAG_H
355