OpenWalnut  1.4.0
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, 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