OpenWalnut 1.2.5
WFlag.h
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, 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, 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( 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()( 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( 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     /**
00190      * The condition to be used for waiting/notifying. Please note, that it gets deleted during destruction.
00191      */
00192     boost::shared_ptr< WCondition > m_condition;
00193 
00194     /**
00195      * This condition is fired whenever the value changes. In contrast to m_condition, this also fires if set() is called with
00196      * suppressNotification=true.
00197      */
00198     boost::shared_ptr< WCondition > m_valueChangeCondition;
00199 
00200     /**
00201      * The flag value.
00202      */
00203     T m_flag;
00204 
00205     /**
00206      * Denotes whether the value has changed since the last reset.
00207      */
00208     bool m_changed;
00209 
00210 private:
00211 };
00212 
00213 /**
00214  * Alias for easy usage of WFLag< bool >.
00215  */
00216 typedef WFlag< bool > WBoolFlag;
00217 
00218 template < typename T >
00219 WFlag< T >::WFlag( WCondition* condition, T initial ):
00220     m_condition( boost::shared_ptr< WCondition >( condition ) ),
00221     m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00222     m_flag( initial ),
00223     m_changed( true )
00224 {
00225 }
00226 
00227 template < typename T >
00228 WFlag< T >::WFlag( boost::shared_ptr< WCondition > condition, T initial ):
00229     m_condition( condition ),
00230     m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00231     m_flag( initial ),
00232     m_changed( true )
00233 {
00234 }
00235 
00236 template < typename T >
00237 WFlag< T >::WFlag( const WFlag& from ):
00238     m_condition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00239     m_valueChangeCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00240     m_flag( from.m_flag ),
00241     m_changed( from.m_changed )
00242 {
00243 }
00244 
00245 template < typename T >
00246 WFlag< T >::~WFlag()
00247 {
00248 }
00249 
00250 template < typename T >
00251 const T WFlag< T >::operator()() const
00252 {
00253     return get();
00254 }
00255 
00256 template < typename T >
00257 const T WFlag< T >::get( bool resetChangeState )
00258 {
00259     if( resetChangeState )
00260     {
00261         m_changed = false;
00262     }
00263     return m_flag;
00264 }
00265 
00266 template < typename T >
00267 const T WFlag< T >::get() const
00268 {
00269     return m_flag;
00270 }
00271 
00272 template < typename T >
00273 WFlag< T >::operator T() const
00274 {
00275     return get();
00276 }
00277 
00278 template < typename T >
00279 void WFlag< T >::wait() const
00280 {
00281     m_condition->wait();
00282 }
00283 
00284 template < typename T >
00285 void WFlag< T >::operator()( T value )
00286 {
00287     set( value );
00288 }
00289 
00290 template < typename T >
00291 bool WFlag< T >::set( T value, bool suppressNotification )
00292 {
00293     // if the value is the same as the current one -> do not notify but let the caller know "all ok"
00294     if( m_flag == value )
00295     {
00296         return true;
00297     }
00298 
00299     // let the caller know whether the value was acceptable.
00300     if( !accept( value ) )
00301     {
00302         return false;
00303     }
00304 
00305     m_flag = value;
00306     m_changed = true;
00307 
00308     // is the notification suppressed ?
00309     if( !suppressNotification )
00310     {
00311         m_condition->notify();
00312     }
00313     m_valueChangeCondition->notify();
00314 
00315     return true;
00316 }
00317 
00318 template < typename T >
00319 boost::shared_ptr< WCondition > WFlag< T >::getCondition()
00320 {
00321     return m_condition;
00322 }
00323 
00324 template < typename T >
00325 boost::shared_ptr< WCondition > WFlag< T >::getValueChangeCondition()
00326 {
00327     return m_valueChangeCondition;
00328 }
00329 
00330 template < typename T >
00331 bool WFlag< T >::accept( T /* newValue */ )
00332 {
00333     // please implement this method in your class to modify the behaviour.
00334     return true;
00335 }
00336 
00337 template < typename T >
00338 bool WFlag< T >::isValid()
00339 {
00340     return accept( get() );
00341 }
00342 
00343 template < typename T >
00344 bool WFlag< T >::changed( bool reset )
00345 {
00346     bool tmp = m_changed;
00347     if( reset )
00348     {
00349         m_changed = false;
00350     }
00351     return tmp;
00352 }
00353 
00354 #endif  // WFLAG_H
00355 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends