Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages

RRefUsage.hh

Go to the documentation of this file.
00001 #ifndef NO_PTR_RREF_USAGE_H
00002 #define NO_PTR_RREF_USAGE_H
00003 
00023 #include <assert.h>
00024 #include "nullness.hh"       // use
00025 #include "RefCountedBool.hh" // contain
00026 #include "NoPtrFwd.hh"
00027 
00028 namespace NoPtr
00029 {
00030     
00031 namespace NoPtrImpl
00032 {
00033     /* This is the base class for RRef usage of DynObj and RRefable's. 
00034        It exposes rather intimate details of verification strategy 
00035        of RRef so make sure derived classes use adequate protection. 
00036        */
00037     class RRefUsage
00038     {
00039         public:
00040             // Just need to make sure pointer is null
00041             RRefUsage(): _state(NullPtr) {}
00042             // nothing special to do since subclasses will decide
00043            ~RRefUsage() {} // proper destruction by method calls
00044             // nothing special to do except shallow copy
00045             RRefUsage(const RRefUsage& rhs): _state(rhs._state) {}
00046             // just want explicit the fact that shallow copy is wanted
00047             void operator=(const RRefUsage& rhs) { _state = rhs._state; }
00048             
00049             // This assumes we've just been default constructed
00050             // and \a rhs has a valid state
00051             void shareFrom(const RRefUsage& rhs)
00052             {
00053                 assert(_state == NullPtr);
00054                 _state = rhs._state;
00055                 assert(_state && _state->valid);
00056                 _state->count ++;
00057             }
00058             // swap with another RRefUsage
00059             void swap(RRefUsage& rhs)
00060             {
00061                 RefCountedBool<>* tmp = _state;
00062                 _state = rhs._state;
00063                 rhs._state = tmp;
00064             }
00065             
00066             // useful for testing; create a state with expected values 
00067             // (or null state) and give it to this method, it will 
00068             // assert that internal state is same as given 
00069             void doAssertState(RefCountedBool<>* state) const 
00070             {
00071                 if (state == NullPtr) assert(_state == NullPtr);
00072                 else assert(*_state == *state);
00073             }
00074             
00075         protected:
00076             RefCountedBool<>* _state;
00077     };
00078     
00079     /* This is the RRefUsage, as seen by an owner of it, i.e. 
00080        a DynObj or an RRefable. The owner is the one who can 
00081        create the RRefUsage state and invalidate it when it is 
00082        destroyed. Though the malicious use of the public interface 
00083        could be very damaging, this object is not accessible 
00084        from outside DynObj and RRef so no special protection is
00085        needed, unlike RRefUsageForUser. 
00086        */
00087     class RRefUsageForOwner: public RRefUsage
00088     {
00089         public:
00090             void swap(RRefUsageForOwner& rhs) {RRefUsage::swap(rhs);}
00091             // create if doesn't already exist
00092             void create()
00093             {
00094                 if (_state == NullPtr) 
00095                     _state = new RefCountedBool<>(true);
00096             }
00097             // if state exists, dec ref count and delete if last one
00098             void destroy() 
00099             {
00100                if (_state)
00101                {
00102                    if (-- _state->count) _state->valid = false;
00103                    else delete _state;
00104                }
00105             }
00106             // Does nothing if no state or we are only user (count=1).
00107             // Otherwise, do invalidate and dec ref count and leave it
00108             // to other(s) to delete later
00109             void reset()
00110             {
00111                if (_state && _state->count > 1) 
00112                {   
00113                    _state->count --;
00114                    _state->valid = false;
00115                    _state = NullPtr;
00116                }
00117                // else no _state or = 1 so nothing to do
00118             }
00119             
00120             // could be done with swap but more efficient
00121             void moveTo(RRefUsageForOwner& rhs)
00122             {
00123                 assert(rhs._state == NullPtr);
00124                 rhs._state = _state;
00125                 _state = NullPtr;
00126             }
00127     };
00128     
00129     /* This is an RRefUsage as seen by a user, i.e. by RRef. 
00130        The state of this object could be obtained and manipulated
00131        with the right call to DynObj or RRefable so we make 
00132        it creatable only by RRef, from which it can never be
00133        obtained. Of course, an adequate specialization of RRef
00134        could get around that but it at least protects against 
00135        inadvertent or hacky use (but not against malicious use, 
00136        which is nigh impossible in C++). 
00137        */
00138     class RRefUsageForUser: public RRefUsage
00139     {
00140         private:
00141             // only RRef can create us
00142             template <typename> friend class ::NoPtr::RRef;
00143             RRefUsageForUser() {}
00144         
00145         public:
00146             void swap(RRefUsageForUser& rhs) {RRefUsage::swap(rhs);}
00147 
00148             // false if no state or state invalid, true otherwise
00149             bool isValid() const {return _state && _state->valid;}
00150             // if state exists, just dec ref count and delete if 
00151             // last one; don't change validity; do nothing if no state
00152             void destroy() 
00153             {
00154                if (_state && !(-- _state->count)) delete _state;
00155             }
00156             // if no state, does nothing; otherwise, dec ref count
00157             // and if last one, delete it; state is null upon
00158             // return in \em all cases
00159             void reset()
00160             {
00161                if (_state) 
00162                {   
00163                    if ( (-- _state->count) == 0)
00164                    {
00165                        // obj *must* have been destroyed
00166                        assert(! _state->valid);
00167                        delete _state;
00168                    }
00169                    _state = NullPtr;
00170                }
00171                // else no _state or = 1 so nothing to do
00172             }
00173             
00174     };
00175     
00176 
00177 } // NoPtrImpl namespace
00178 
00179 } // NoPtr namespace
00180 
00181 #endif // NO_PTR_RREF_USAGE_H

Generated on Mon Aug 4 18:51:24 2003 for NoPtr C++ Library by doxygen 1.3.2