OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WFLAG_H 00026 #define WFLAG_H 00027 00028 #include <boost/shared_ptr.hpp> 00029 00030 #include "WCondition.h" 00031 00032 /** 00033 * Class to have a simple notification/condition system for simple flags. This is somewhat similar to the observer design pattern. 00034 * The type of the flag is specified by the template parameter. Per default, it is of type bool. 00035 */ 00036 template < typename T > 00037 class WFlag 00038 { 00039 public: 00040 /** 00041 * The type for later access. 00042 */ 00043 typedef T ValueType; 00044 00045 /** 00046 * Convenience typedef for a boost::shared_ptr. 00047 */ 00048 typedef boost::shared_ptr< WFlag< T > > SPtr; 00049 00050 /** 00051 * Convenience typedef for a boost::shared_ptr. Const. 00052 */ 00053 typedef boost::shared_ptr< const WFlag< T > > ConstSPtr; 00054 00055 /** 00056 * Constructor. Uses a given condition to realize the wait/notify functionality. By using this constructor, the specified 00057 * condition gets deleted whenever this WFlag is deleted. 00058 * 00059 * \param condition the condition to use. 00060 * \note condition can also be a WConditionOneShot. 00061 * \param initial the initial value of this flag. 00062 */ 00063 WFlag( WCondition* condition, const T& initial ); 00064 00065 /** 00066 * Constructor. Uses a given condition to realize the wait/notify functionality. By using this constructor, the specified 00067 * condition gets NOT explicitely deleted when this WFlag gets deleted. 00068 * 00069 * \param condition the condition to use. 00070 * \note condition can also be a WConditionOneShot. 00071 * \param initial the initial value of this flag. 00072 */ 00073 WFlag( boost::shared_ptr< WCondition > condition, const T& initial ); 00074 00075 /** 00076 * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get 00077 * created. The subscriptions to a signal are LOST as well as all listeners to a condition. 00078 * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because 00079 * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original flag is changed 00080 * (which after cloning is completely decoupled from the clone). 00081 * 00082 * \param from the instance to copy. 00083 */ 00084 explicit WFlag( const WFlag& from ); 00085 00086 /** 00087 * Destructor. It deletes the instance of WCondition specified on construction. 00088 */ 00089 virtual ~WFlag(); 00090 00091 /** 00092 * Operator returns value of the flag. 00093 * 00094 * \param resetChangeState when true, the changed() flag gets reset to false. 00095 * 00096 * \return the value. 00097 */ 00098 virtual const T& get( bool resetChangeState = false ); 00099 00100 /** 00101 * Operator returns value of the flag. 00102 * 00103 * \return the value. 00104 */ 00105 virtual const T& get() const; 00106 00107 /** 00108 * Operator returns value of the flag. 00109 * 00110 * \return the value. 00111 */ 00112 virtual const T& operator()() const; 00113 00114 /** 00115 * Operator returns value of the flag. It does not reset the change flag. 00116 * 00117 * \return the value. 00118 */ 00119 virtual operator T() const; 00120 00121 /** 00122 * Wait for the flag to change its value. For WConditionOneShot is also recognizes if the flag has changed before. 00123 */ 00124 virtual void wait() const; 00125 00126 /** 00127 * Sets the new value for this flag. Also notifies waiting threads. After setting a value, changed() will be true. 00128 * 00129 * \param value the new value 00130 * \param suppressNotification true to avoid a firing condition. This is useful for resetting values. 00131 * 00132 * \return true if the value has been set successfully. 00133 * 00134 * \note set( get() ) == true 00135 */ 00136 virtual bool set( const T& value, bool suppressNotification = false ); 00137 00138 /** 00139 * Sets the new value for this flag. Also notifies waiting threads. 00140 * 00141 * \param value the new value 00142 */ 00143 virtual void operator()( const T& value ); 00144 00145 /** 00146 * Returns the condition that is used by this flag. 00147 * 00148 * \return the condition 00149 */ 00150 boost::shared_ptr< WCondition > getCondition(); 00151 00152 /** 00153 * Returns the condition denoting a value change. In contrast to getCondition, this condition fires regardless of notification is suppressed 00154 * during set() or not. 00155 * 00156 * \return the condition denoting a value change. 00157 */ 00158 boost::shared_ptr< WCondition > getValueChangeCondition(); 00159 00160 /** 00161 * Determines whether the specified value is acceptable. In WFlags, this always returns true. To modify the behaviour, 00162 * implement this function in an appropriate way. 00163 * 00164 * \param newValue the new value. 00165 * 00166 * \return true if it is a valid/acceptable value. 00167 */ 00168 virtual bool accept( const T& newValue ); 00169 00170 /** 00171 * Tests whether a flag is currently valid. It is equal to accept( get() ); 00172 * 00173 * \return true if current value is valid. 00174 */ 00175 virtual bool isValid(); 00176 00177 /** 00178 * 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 00179 * true. 00180 * 00181 * \param reset if true, the change flag gets reset. 00182 * 00183 * \return true when the value has changed and not yet been reseted. 00184 */ 00185 virtual bool changed( bool reset = false ); 00186 00187 protected: 00188 /** 00189 * The condition to be used for waiting/notifying. Please note, that it gets deleted during destruction. 00190 */ 00191 boost::shared_ptr< WCondition > m_condition; 00192 00193 /** 00194 * This condition is fired whenever the value changes. In contrast to m_condition, this also fires if set() is called with 00195 * suppressNotification=true. 00196 */ 00197 boost::shared_ptr< WCondition > m_valueChangeCondition; 00198 00199 /** 00200 * The flag value. 00201 */ 00202 T m_flag; 00203 00204 /** 00205 * Denotes whether the value has changed since the last reset. 00206 */ 00207 bool m_changed; 00208 00209 private: 00210 }; 00211 00212 /** 00213 * Alias for easy usage of WFLag< bool >. 00214 */ 00215 typedef WFlag< bool > WBoolFlag; 00216 00217 template < typename T > 00218 WFlag< T >::WFlag( WCondition* condition, const T& initial ): 00219 m_condition( boost::shared_ptr< WCondition >( condition ) ), 00220 m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ), 00221 m_flag( initial ), 00222 m_changed( true ) 00223 { 00224 } 00225 00226 template < typename T > 00227 WFlag< T >::WFlag( boost::shared_ptr< WCondition > condition, const T& initial ): 00228 m_condition( condition ), 00229 m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ), 00230 m_flag( initial ), 00231 m_changed( true ) 00232 { 00233 } 00234 00235 template < typename T > 00236 WFlag< T >::WFlag( const WFlag& from ): 00237 m_condition( boost::shared_ptr< WCondition >( new WCondition() ) ), 00238 m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ), 00239 m_flag( from.m_flag ), 00240 m_changed( from.m_changed ) 00241 { 00242 } 00243 00244 template < typename T > 00245 WFlag< T >::~WFlag() 00246 { 00247 } 00248 00249 template < typename T > 00250 const T& WFlag< T >::operator()() const 00251 { 00252 return get(); 00253 } 00254 00255 template < typename T > 00256 const T& WFlag< T >::get( bool resetChangeState ) 00257 { 00258 if( resetChangeState ) 00259 { 00260 m_changed = false; 00261 } 00262 return m_flag; 00263 } 00264 00265 template < typename T > 00266 const T& WFlag< T >::get() const 00267 { 00268 return m_flag; 00269 } 00270 00271 template < typename T > 00272 WFlag< T >::operator T() const 00273 { 00274 return get(); 00275 } 00276 00277 template < typename T > 00278 void WFlag< T >::wait() const 00279 { 00280 m_condition->wait(); 00281 } 00282 00283 template < typename T > 00284 void WFlag< T >::operator()( const T& value ) 00285 { 00286 set( value ); 00287 } 00288 00289 template < typename T > 00290 bool WFlag< T >::set( const T& value, bool suppressNotification ) 00291 { 00292 // if the value is the same as the current one -> do not notify but let the caller know "all ok" 00293 if( m_flag == value ) 00294 { 00295 return true; 00296 } 00297 00298 // let the caller know whether the value was acceptable. 00299 if( !accept( value ) ) 00300 { 00301 return false; 00302 } 00303 00304 m_flag = value; 00305 m_changed = true; 00306 00307 // is the notification suppressed ? 00308 if( !suppressNotification ) 00309 { 00310 m_condition->notify(); 00311 } 00312 m_valueChangeCondition->notify(); 00313 00314 return true; 00315 } 00316 00317 template < typename T > 00318 boost::shared_ptr< WCondition > WFlag< T >::getCondition() 00319 { 00320 return m_condition; 00321 } 00322 00323 template < typename T > 00324 boost::shared_ptr< WCondition > WFlag< T >::getValueChangeCondition() 00325 { 00326 return m_valueChangeCondition; 00327 } 00328 00329 template < typename T > 00330 bool WFlag< T >::accept( const T& /* newValue */ ) 00331 { 00332 // please implement this method in your class to modify the behaviour. 00333 return true; 00334 } 00335 00336 template < typename T > 00337 bool WFlag< T >::isValid() 00338 { 00339 return accept( get() ); 00340 } 00341 00342 template < typename T > 00343 bool WFlag< T >::changed( bool reset ) 00344 { 00345 bool tmp = m_changed; 00346 if( reset ) 00347 { 00348 m_changed = false; 00349 } 00350 return tmp; 00351 } 00352 00353 #endif // WFLAG_H 00354