00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ARCHON_UTILITIES_REF_H
00021 #define ARCHON_UTILITIES_REF_H
00022
00023 #include <string>
00024 #include <vector>
00025 #include <algorithm>
00026
00027 #include <archon/util/exception.H>
00028 #include <archon/util/mutex.H>
00029
00030 #include <archon/util/cxx_demangle.H>
00031
00032 namespace Archon
00033 {
00034 namespace Utilities
00035 {
00036 using namespace std;
00037
00038 template<typename T> struct BackRef;
00039 struct RefMapBase;
00040 template<typename T> struct RefMap;
00041 struct Thread;
00042
00043 struct ForwardDestroyedException: Exception
00044 {
00045 ForwardDestroyedException(string l): Exception(l) {}
00046 };
00047
00048
00052 struct RefNoLockTag {};
00053
00057 struct RefSafeIncTag {};
00058
00059
00166 template<typename T>
00167 struct Ref
00168 {
00169 typedef T ObjectType;
00170
00171 Ref(): p(0) {}
00172
00177 Ref(T *p): p(p) { inc(); }
00178
00179 Ref(const Ref &r): p(r.p) { inc(); }
00180 template<typename U> Ref(const Ref<U> &r): p(r.p) { inc(); }
00181
00182 ~Ref() { dec(); }
00183
00191 void reset(T *p=0);
00192
00197 void swap(Ref &r) { std::swap(p, r.p); }
00198
00199 Ref &operator=(const Ref &);
00200 template<typename U> Ref &operator=(const Ref<U> &);
00201
00202 template<typename U> bool operator==(const Ref<U> &) const;
00203 template<typename U> bool operator!=(const Ref<U> &) const;
00204 template<typename U> bool operator<(const Ref<U> &) const;
00205 template<typename U> bool operator>(const Ref<U> &) const;
00206
00210 T *operator->() const;
00211
00212 operator bool() const { return p; }
00213
00225 T *get() const { return p; }
00226
00230 bool sole() const { return p && p->refSole(); }
00231
00232
00237 Ref(T *p, RefNoLockTag): p(p) { incNoLock(); }
00238
00239
00380 Ref(T *p, RefSafeIncTag);
00381
00382 private:
00383 template<typename U> friend struct Ref;
00384 friend struct BackRef<T>;
00385 friend struct RefMap<T>;
00386
00387 T *p;
00388
00389 void inc() const { if(p) p->refInc(); }
00390 void dec() const { if(p) p->refDec(); }
00391
00392 void incNoLock() const { if(p) p->refIncNoLock(); }
00393 };
00394
00395
00396
00423 struct RefObjectBase: protected virtual Mutex
00424 {
00428 virtual ~RefObjectBase() {}
00429
00430 unsigned long getUseCount() const;
00431
00432 protected:
00433 RefObjectBase(): useCount(0) {}
00434
00456 virtual void refDispose(Mutex::Lock &);
00457
00458 unsigned long getUseCountNoLock() const { return useCount; }
00459
00460 private:
00461 template<typename T> friend struct Ref;
00462 template<typename T> friend struct BackRef;
00463 friend struct BackRefObjectBase;
00464 friend struct RefMapBase;
00465 friend struct Thread;
00466
00467 void refInc() const;
00468 void refDec() const;
00469
00470 void refIncNoLock() const;
00471
00475 virtual bool refTryInc() const;
00476
00480 bool refSole() const;
00481
00482 mutable unsigned long useCount;
00483 };
00484
00485
00486 typedef Ref<RefObjectBase> RefAny;
00487 typedef Ref<const RefObjectBase> RefAnyConst;
00488
00489
00497 template<typename T>
00498 struct RefObject: virtual RefObjectBase
00499 {
00500 T value;
00501 RefObject(T v): value(v) {}
00502 };
00503
00504
00505
00506
00624 template<typename T>
00625 struct BackRef
00626 {
00627 typedef T ObjectType;
00628
00629 BackRef(): p(0) {}
00630
00631 BackRef(const Ref<T> &r): p(r.get()) { inc(); }
00632 BackRef(const BackRef &r): p(r.p) { inc(); }
00633 template<typename U> BackRef(const BackRef<U> &r): p(r.p) { inc(); }
00634
00635 ~BackRef() { dec(); }
00636
00641 void reset() { reset(0); }
00642
00647 void reset(const Ref<T> &r) { reset(r.p); }
00648
00653 void swap(BackRef &r) { std::swap(p, r.p); }
00654
00655 BackRef &operator=(const BackRef &);
00656 template<typename U> BackRef &operator=(const BackRef<U> &);
00657
00658 template<typename U> bool operator==(const BackRef<U> &) const;
00659 template<typename U> bool operator!=(const BackRef<U> &) const;
00660
00661 template<typename U> bool operator==(const Ref<U> &) const;
00662 template<typename U> bool operator!=(const Ref<U> &) const;
00663
00664 template<typename U> bool operator==(const U *) const;
00665 template<typename U> bool operator!=(const U *) const;
00666
00670 Ref<T> operator->() const throw(ForwardDestroyedException);
00671
00672 operator bool() const { return p; }
00673
00674 Ref<T> getRef() const throw(ForwardDestroyedException);
00675
00676 private:
00677 template<typename U> friend struct BackRef;
00678
00679 T *p;
00680
00681 void reset(T *p);
00682
00683 void inc() const { if(p) p->backRefInc(); }
00684 void dec() const { if(p) p->backRefDec(); }
00685 };
00686
00687
00695 struct BackRefObjectBase: virtual RefObjectBase
00696 {
00697 unsigned long getBackUseCount() const;
00698
00699 protected:
00700 BackRefObjectBase(): backUseCount(0), forwardDestroyed(false) {}
00701
00702 virtual void refDispose(Mutex::Lock &);
00703
00725 virtual void refForwardDestroy() = 0;
00726
00727 unsigned long getBackUseCountNoLock() const { return backUseCount; }
00728
00729 private:
00730 template<typename T> friend struct Ref;
00731 template<typename T> friend struct BackRef;
00732
00733 void backRefInc() const;
00734 void backRefDec() const;
00735
00736 virtual bool refTryInc() const;
00737
00738 mutable unsigned long backUseCount;
00739 bool forwardDestroyed;
00740 };
00741
00742
00743
00744
00745
00751 struct RefMapBase
00752 {
00753 protected:
00754 unsigned long get(RefObjectBase *, bool create);
00755
00756 RefObjectBase *getNoLock(unsigned long key) const
00757 {
00758 return key < refs.size() ? refs[key].first : 0;
00759 }
00760
00761 void remove(unsigned long key, unsigned long transCount)
00762 {
00763 if(!key) return;
00764 Mutex::Lock l(refMapMutex);
00765 if(key >= refs.size()) return;
00766 removeNoLock(refs[key].first, transCount);
00767 }
00768
00769 void remove(RefObjectBase *r)
00770 {
00771 Mutex::Lock l(refMapMutex);
00772 removeNoLock(r, 0);
00773 }
00774
00775 void clearNoLock(bool destroyRefs);
00776
00777 Mutex refMapMutex;
00778
00779 vector<pair<RefObjectBase *, unsigned long> > refs;
00780
00781 unsigned long size()
00782 {
00783 Mutex::Lock l(refMapMutex);
00784 return refs.size() - unused.size() - 1;
00785 }
00786
00787 string disp();
00788
00789 RefMapBase();
00790 ~RefMapBase();
00791
00792 private:
00793 static const unsigned long hashSize = 127;
00794
00795 vector<unsigned long> *chunks[hashSize];
00796 vector<unsigned long> unused;
00797
00798 void removeNoLock(RefObjectBase *, unsigned long transCount);
00799 };
00800
00874 template<typename T>
00875 struct RefMap: private RefMapBase
00876 {
00880 RefMapBase::size;
00881
00885 RefMapBase::disp;
00886
00896 unsigned long get(Ref<T> r, bool create=true)
00897 {
00898 return RefMapBase::get(const_cast<RefObjectBase *>
00899 (static_cast<const RefObjectBase *>
00900 (r.get())), create);
00901 }
00902
00914 Ref<T> operator()(unsigned long key) const
00915 {
00916 Mutex::Lock l(refMapMutex);
00917 return dynamic_cast<T *>(getNoLock(key));
00918 }
00919
00927 void remove(unsigned long key, unsigned long transCount=0)
00928 {
00929 RefMapBase::remove(key, transCount);
00930 }
00931
00936 void remove(Ref<T> r)
00937 {
00938 RefMapBase::remove(const_cast<RefObjectBase *>
00939 (static_cast<const RefObjectBase *>(r.get())));
00940 }
00941
00942 void clear(vector<Ref<T> > *remains = 0)
00943 {
00944 if(remains)
00945 {
00946 remains->clear();
00947 remains->resize(size());
00948 Mutex::Lock l(refMapMutex);
00949 unsigned j = 0;
00950 for(unsigned i = 1; i<refs.size(); ++i)
00951 {
00952 RefObjectBase *r = refs[i].first;
00953 if(r) remains->operator[](j++).p = dynamic_cast<T *>(r);
00954 }
00955 RefMapBase::clearNoLock(false);
00956 }
00957 else
00958 {
00959 Mutex::Lock l(refMapMutex);
00960 RefMapBase::clearNoLock(true);
00961 }
00962 }
00963 };
00964
00965
00966
00967
00968
00969 template<typename T>
00970 inline void Ref<T>::reset(T *_p)
00971 {
00972 if(p == _p) return;
00973 dec();
00974 p = _p;
00975 inc();
00976 }
00977
00978 template<typename T>
00979 inline Ref<T> &Ref<T>::operator=(const Ref &r)
00980 {
00981 reset(r.p);
00982 return *this;
00983 }
00984
00985 template<typename T> template<typename U>
00986 inline Ref<T> &Ref<T>::operator=(const Ref<U> &r)
00987 {
00988 reset(r.p);
00989 return *this;
00990 }
00991
00992 template<typename T> template<typename U>
00993 inline bool Ref<T>::operator==(const Ref<U> &r) const
00994 {
00995 return p == r.p;
00996 }
00997
00998 template<typename T> template<typename U>
00999 inline bool Ref<T>::operator!=(const Ref<U> &r) const
01000 {
01001 return p != r.p;
01002 }
01003
01004 template<typename T> template<typename U>
01005 inline bool Ref<T>::operator<(const Ref<U> &r) const
01006 {
01007 return p < r.p;
01008 }
01009
01010 template<typename T> template<typename U>
01011 inline bool Ref<T>::operator>(const Ref<U> &r) const
01012 {
01013 return p > r.p;
01014 }
01015
01016 template<typename T>
01017 inline T *Ref<T>::operator->() const
01018 {
01019 if(p) return p;
01020 ARCHON_THROW1(StateException, "Dereferencing null");
01021 }
01022
01023 template<typename T>
01024 inline Ref<T>::Ref(T *_p, RefSafeIncTag): p(0)
01025 {
01026 if(_p && _p->refTryInc()) p = _p;
01027 }
01028
01029
01030
01031 inline void RefObjectBase::refInc() const
01032 {
01033 Mutex::Lock l(*this);
01034 ++useCount;
01035 }
01036
01037 inline void RefObjectBase::refDec() const
01038 {
01039 Mutex::Lock l(*this);
01040 if(!--useCount) const_cast<RefObjectBase *>(this)->refDispose(l);
01041 }
01042
01043 inline void RefObjectBase::refIncNoLock() const
01044 {
01045 ++useCount;
01046 }
01047
01048 inline void RefObjectBase::refDispose(Mutex::Lock &l)
01049 {
01050 l.release();
01051
01052
01053
01054 delete this;
01055 }
01056
01057 inline bool RefObjectBase::refTryInc() const
01058 {
01059 Mutex::Lock l(*this);
01060 if(useCount)
01061 {
01062 ++useCount;
01063 return true;
01064 }
01065 return false;
01066 }
01067
01068 inline bool RefObjectBase::refSole() const
01069 {
01070 Mutex::Lock l(*this);
01071 return useCount == 1;
01072 }
01073
01074 inline unsigned long RefObjectBase::getUseCount() const
01075 {
01076 Mutex::Lock l(*this);
01077 return useCount;
01078 }
01079
01080
01081
01082
01083 template<typename T>
01084 inline void BackRef<T>::reset(T *_p)
01085 {
01086 if(p == _p) return;
01087 dec();
01088 p = _p;
01089 inc();
01090 }
01091
01092 template<typename T>
01093 inline BackRef<T> &BackRef<T>::operator=(const BackRef &r)
01094 {
01095 reset(r.p);
01096 return *this;
01097 }
01098
01099 template<typename T> template<typename U>
01100 inline BackRef<T> &BackRef<T>::operator=(const BackRef<U> &r)
01101 {
01102 reset(r.p);
01103 return *this;
01104 }
01105
01106 template<typename T> template<typename U>
01107 inline bool BackRef<T>::operator==(const BackRef<U> &r) const
01108 {
01109 return p == r.p;
01110 }
01111
01112 template<typename T> template<typename U>
01113 inline bool BackRef<T>::operator!=(const BackRef<U> &r) const
01114 {
01115 return p != r.p;
01116 }
01117
01118 template<typename T> template<typename U>
01119 inline bool BackRef<T>::operator==(const Ref<U> &r) const
01120 {
01121 return p == r.get();
01122 }
01123
01124 template<typename T> template<typename U>
01125 inline bool BackRef<T>::operator!=(const Ref<U> &r) const
01126 {
01127 return p != r.get();
01128 }
01129
01130 template<typename T> template<typename U>
01131 inline bool BackRef<T>::operator==(const U *r) const
01132 {
01133 return p == r;
01134 }
01135
01136 template<typename T> template<typename U>
01137 inline bool BackRef<T>::operator!=(const U *r) const
01138 {
01139 return p != r;
01140 }
01141
01142 template<typename T>
01143 inline Ref<T> BackRef<T>::getRef() const throw(ForwardDestroyedException)
01144 {
01145 if(!p) return 0;
01146 Ref<T> r(p, RefSafeIncTag());
01147 if(!r) ARCHON_THROW(ForwardDestroyedException);
01148 return r;
01149 }
01150
01151 template<typename T>
01152 inline Ref<T> BackRef<T>::operator->() const
01153 throw(ForwardDestroyedException)
01154 {
01155 if(!p) return 0;
01156 Ref<T> r(p, RefSafeIncTag());
01157 if(!r) ARCHON_THROW(ForwardDestroyedException);
01158 return r;
01159 }
01160
01161
01162
01163
01164 inline void BackRefObjectBase::backRefInc() const
01165 {
01166 Mutex::Lock l(*this);
01167 ++backUseCount;
01168 }
01169
01170 inline void BackRefObjectBase::backRefDec() const
01171 {
01172 Mutex::Lock l(*this);
01173 if(!--backUseCount) const_cast<BackRefObjectBase *>(this)->refDispose(l);
01174 }
01175
01176
01177 inline bool BackRefObjectBase::refTryInc() const
01178 {
01179 Mutex::Lock l(*this);
01180 if(useCount&&!forwardDestroyed)
01181 {
01182 ++useCount;
01183 return true;
01184 }
01185 return false;
01186 }
01187
01188
01189 inline void BackRefObjectBase::refDispose(Mutex::Lock &l)
01190 {
01191 if(!useCount)
01192 {
01193 if(!backUseCount)
01194 {
01195 l.release();
01196
01197
01198
01199
01200 delete this;
01201 return;
01202 }
01203
01204 if(forwardDestroyed) return;
01205 forwardDestroyed = true;
01206 Ref<BackRefObjectBase> r(this, RefNoLockTag());
01207 l.release();
01208 r->refForwardDestroy();
01209 }
01210 }
01211
01212 inline unsigned long BackRefObjectBase::getBackUseCount() const
01213 {
01214 Mutex::Lock l(*this);
01215 return backUseCount;
01216 }
01217 }
01218 }
01219
01220 namespace std
01221 {
01222 template<typename T>
01223 void swap(Archon::Utilities::Ref<T> &r,
01224 Archon::Utilities::Ref<T> &s)
01225 {
01226 r.swap(s);
01227 }
01228
01229 template<typename T>
01230 void swap(Archon::Utilities::BackRef<T> &r,
01231 Archon::Utilities::BackRef<T> &s)
01232 {
01233 r.swap(s);
01234 }
01235 }
01236
01237 #endif // ARCHON_UTILITIES_REF_H