00001
00020 #ifndef MANGO_PTR_SHARED_VALIDATOR_H
00021 #define MANGO_PTR_SHARED_VALIDATOR_H
00022
00023 #include <assert.h>
00024 #include <algorithm>
00025 #include "nullness.hh"
00026
00027 namespace MangoPtr
00028 {
00029
00030 class SharedValidity
00031 {
00032 private:
00034 struct State
00035 {
00037 static const unsigned short bitsPerByte = 8;
00039 static const size_t countBits = bitsPerByte*sizeof(size_t) - 1;
00040
00041 size_t count:countBits;
00042 size_t valid:1;
00043
00045 State(): count(1), valid(false) {}
00046 };
00047
00048 protected:
00050 SharedValidity(): state(NullPtr) {}
00051 inline SharedValidity(bool);
00052 inline SharedValidity(const SharedValidity&);
00053 inline SharedValidity& operator=(const SharedValidity&);
00055 inline ~SharedValidity() { if (isNotNull(state)) freeCount(); }
00056 inline void reset(bool);
00057 inline void setValid(bool);
00058
00059 public:
00061 bool isValid() const {return (isNotNull(state)) && state->valid;}
00063 bool isShared() const {return (isNotNull(state)) && state->count > 1;}
00064 size_t getRefCount() const {return isNull(state) ? 1 : state->count;}
00066 inline void swap(SharedValidity& rhs) { std::swap(state, rhs.state); }
00067
00068 #if ! defined NDEBUG && defined TEST_SHARED
00069 static void setDeleted(bool);
00070 static void test();
00071 #endif
00072
00073 private:
00075 void setValid() {assert(isNotNull(state)); state->valid = true;}
00077 void setInvalid() {assert(isNotNull(state)); state->valid = false;}
00078
00079 static inline State* newCount();
00080 inline State* getCountPtr() const;
00081 inline void freeCount();
00082
00083 private:
00085
00088
00089 };
00090
00096 inline
00097 SharedValidity::SharedValidity(const bool valid)
00098 : state(NullPtr)
00099 {
00100
00101
00102 if (valid)
00103 {
00104 state = newCount();
00105 setValid();
00106 }
00107 }
00108
00115 inline
00116 SharedValidity::SharedValidity(const SharedValidity& vv)
00117 : state(vv.getCountPtr())
00118 {
00119 assert(isNotNull(state));
00120 state->count ++;
00121 }
00122
00131 inline SharedValidity&
00132 SharedValidity::operator=(const SharedValidity& vv)
00133 {
00134 State* const tmp = vv.getCountPtr();
00135 if (tmp != state)
00136 {
00137 if (isNotNull(state)) freeCount();
00138 (state = tmp)->count ++;
00139 }
00140 return *this;
00141 }
00142
00149 inline SharedValidity::State*
00150 SharedValidity::newCount()
00151 {
00152 #if ! defined NDEBUG && defined TEST_SHARED
00153 setDeleted(false);
00154 #endif
00155 return new State;
00156 }
00157
00162 inline void
00163 SharedValidity::freeCount()
00164 {
00165 assert(isNotNull(state));
00166 state->count --;
00167
00168 if (0 == state->count)
00169 {
00170 delete state;
00171 #if ! defined NDEBUG && defined TEST_SHARED
00172 setDeleted(true);
00173 #endif
00174 }
00175 }
00176
00183 inline SharedValidity::State*
00184 SharedValidity::getCountPtr()
00185 const
00186 {
00187 if (isNull(state)) state = newCount();
00188 assert(isNotNull(state));
00189 return state;
00190 }
00191
00197 inline void
00198 SharedValidity::setValid(const bool valid)
00199 {
00200 if (valid)
00201 {
00202 if (isNull(state)) state = newCount();
00203 setValid();
00204 }
00205 else
00206 {
00207 if (isValid()) setInvalid();
00208 }
00209 }
00210
00218 inline void
00219 SharedValidity::reset(const bool valid)
00220 {
00221 if (isShared())
00222 {
00223 assert(isNotNull(state));
00224 if (valid)
00225 {
00226 State* tmp = newCount();
00227 state->count --;
00228 state = tmp;
00229 setValid();
00230 }
00231 else
00232 {
00233 state->count --;
00234 nullify(state);
00235 }
00236 }
00237 else setValid(valid);
00238 }
00239
00240 }
00241
00272 #endif // MANGO_PTR_SHARED_VALIDATOR_H
00273