RefCount.h

00001 /* This file is Copyright 2000-2008 Meyer Sound Laboratories Inc.  See the included LICENSE.txt file for details. */ 
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) {/* empty */}
00021 
00023    RefCountable(const RefCountable &) : _manager(NULL) {/* empty */}
00024 
00026    virtual ~RefCountable() {/* empty */}
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;  // forward reference
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) {/* empty */}
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                // We weren't ref-counting before, but the user wants us to start
00134                _doRefCount = true;
00135                RefItem();
00136             }
00137             else 
00138             {
00139                // We were ref-counting before, but the user wants us to drop it
00140                UnrefItem();
00141                _doRefCount = false;
00142             } 
00143          }
00144       }
00145       else
00146       {
00147          // switch items
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);}  // double-cast for AMD64
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 // VC++6 and ealier can't handle partial template specialization, so don't let it see this
00308 // To compile using them, you'll have to write an explicit HashFunctor.  Sucks, eh?
00309 // At least you can use the DECLARE_HASHTABLE_KEY_CLASS macro to make it quicker for you.
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

Generated on Thu Jun 5 17:47:54 2008 for MUSCLE by  doxygen 1.5.1