00001
00002
00003 #ifndef MuscleRefCount_h
00004 #define MuscleRefCount_h
00005
00006 #include "util/ObjectPool.h"
00007 #include "system/AtomicCounter.h"
00008
00009 BEGIN_NAMESPACE(muscle);
00010
00011 class RefCountable;
00012
00016 class RefCountable
00017 {
00018 public:
00020 RefCountable() : _manager(NULL) {}
00021
00023 RefCountable(const RefCountable &) : _manager(NULL) {}
00024
00026 virtual ~RefCountable() {}
00027
00029 inline RefCountable &operator=(const RefCountable &) {return *this;}
00030
00032 inline void IncrementRefCount() const {_refCount.AtomicIncrement();}
00033
00035 inline bool DecrementRefCount() const {return _refCount.AtomicDecrement();}
00036
00044 void SetManager(AbstractObjectManager * manager) {_manager = manager;}
00045
00047 AbstractObjectManager * GetManager() const {return _manager;}
00048
00054 uint32 GetRefCount() const {return _refCount.GetCount();}
00055
00056 private:
00057 mutable AtomicCounter _refCount;
00058 AbstractObjectManager * _manager;
00059 };
00060
00061 template <class Item> class Ref;
00062
00064 typedef Ref<RefCountable> GenericRef;
00065
00070 template <class Item> class Ref
00071 {
00072 public:
00073 typedef ObjectPool<Item> ItemPool;
00079 Ref() : _item(NULL), _doRefCount(true) {}
00080
00093 Ref(Item * item, bool doRefCount = true) : _item(item), _doRefCount(doRefCount) {RefItem();}
00094
00098 Ref(const Ref & copyMe) : _item(NULL), _doRefCount(true) {*this = copyMe;}
00099
00105 Ref(const GenericRef & ref, bool junk) : _item(NULL), _doRefCount(true) {(void) junk; (void) SetFromGeneric(ref);}
00106
00110 ~Ref() {UnrefItem();}
00111
00125 void SetRef(Item * item, bool doRefCount = true)
00126 {
00127 if (item == _item)
00128 {
00129 if (doRefCount != _doRefCount)
00130 {
00131 if (doRefCount)
00132 {
00133
00134 _doRefCount = true;
00135 RefItem();
00136 }
00137 else
00138 {
00139
00140 UnrefItem();
00141 _doRefCount = false;
00142 }
00143 }
00144 }
00145 else
00146 {
00147
00148 UnrefItem();
00149 _item = item;
00150 _doRefCount = doRefCount;
00151 RefItem();
00152 }
00153 }
00154
00158 inline Ref &operator=(const Ref & rhs) {if (this != &rhs) SetRef(rhs._item, rhs._doRefCount); return *this;}
00159
00161 bool operator ==(const Ref &rhs) const {return _item == rhs._item;}
00162
00164 bool operator !=(const Ref &rhs) const {return _item != rhs._item;}
00165
00169 Item * GetItemPointer() const {return _item;}
00170
00177 Item * CheckedGetItemPointer() const {return this ? _item : NULL;}
00178
00180 Item * operator()() const {return _item;}
00181
00185 void Reset() {UnrefItem();}
00186
00190 void Neutralize() {if ((_doRefCount)&&(_item)) (void) _item->DecrementRefCount(); _item = NULL;}
00191
00195 void SwapContents(Ref & swapWith)
00196 {
00197 muscleSwap(_item, swapWith._item);
00198 muscleSwap(_doRefCount, swapWith._doRefCount);
00199 }
00200
00204 bool IsRefCounting() const {return _doRefCount;}
00205
00207 GenericRef GetGeneric() const {return GenericRef(_item, _doRefCount);}
00208
00215 status_t SetFromGeneric(const GenericRef & genericRef)
00216 {
00217 RefCountable * genericItem = genericRef();
00218 if (genericItem)
00219 {
00220 Item * typedItem = dynamic_cast<Item *>(genericItem);
00221 if (typedItem == NULL) return B_ERROR;
00222 SetRef(typedItem, genericRef.IsRefCounting());
00223 }
00224 else Reset();
00225
00226 return B_NO_ERROR;
00227 }
00228
00235 inline void SetFromGenericUnchecked(const GenericRef & genericRef)
00236 {
00237 SetRef(static_cast<Item *>(genericRef()), genericRef.IsRefCounting());
00238 }
00239
00246 bool IsRefPrivate() const
00247 {
00248 return ((_item == NULL)||((_doRefCount)&&(_item->GetRefCount() == 1)));
00249 }
00250
00264 status_t EnsureRefIsPrivate()
00265 {
00266 if (IsRefPrivate() == false)
00267 {
00268 AbstractObjectManager * m = _item->GetManager();
00269 Item * newItem = m ? static_cast<Item *>(m->ObtainObjectGeneric()) : newnothrow Item;
00270 if (newItem)
00271 {
00272 *newItem = *_item;
00273 SetRef(newItem);
00274 }
00275 else
00276 {
00277 WARN_OUT_OF_MEMORY;
00278 return B_ERROR;
00279 }
00280 }
00281 return B_NO_ERROR;
00282 }
00283
00285 uint32 HashCode() const {return (uint32)((unsigned long)_item);}
00286
00287 private:
00288 void RefItem() {if ((_doRefCount)&&(_item)) _item->IncrementRefCount();}
00289 void UnrefItem()
00290 {
00291 if (_item)
00292 {
00293 if ((_doRefCount)&&(_item->DecrementRefCount()))
00294 {
00295 AbstractObjectManager * m = _item->GetManager();
00296 if (m) m->RecycleObject(_item);
00297 else delete _item;
00298 }
00299 _item = NULL;
00300 }
00301 }
00302
00303 Item * _item;
00304 bool _doRefCount;
00305 };
00306
00307
00308
00309
00310 #ifndef MUSCLE_USING_OLD_MICROSOFT_COMPILER
00311 template <class T> class HashFunctor;
00312 template <class Item> class HashFunctor<Ref<Item> >
00313 {
00314 public:
00315 uint32 operator()(const Ref<Item> & ref) const {return ref.HashCode();}
00316 };
00317 template <class Item> class HashFunctor<const Ref<Item> * >
00318 {
00319 public:
00320 uint32 operator()(const Ref<Item> * ref) const {return ref->HashCode();}
00321 };
00322 #endif
00323
00324 END_NAMESPACE(muscle);
00325
00326 #endif