Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

refcount.h

/*
 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
 * 
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */


/*
      Based on code donated by Perry Kiehtreiber
 */
#ifndef _SECURITY_REFCOUNT_H_
#define _SECURITY_REFCOUNT_H_

#include <security_utilities/threading.h>

namespace Security {


//
// RefCount/RefPointer - a simple reference counting facility.
//
// To make an object reference-counted, derive it from RefCount. To track refcounted
// objects, use RefPointer<TheType>, where TheType must be derived from RefCount.
//
// RefCount is thread safe - any number of threads can hold and manipulate references
// in parallel. It does however NOT protect the contents of your object - just the
// reference count itself. If you need to share your object contents, you must engage
// in appropriate locking yourself.
//
// There is no (thread safe) way to determine whether you are the only thread holding
// a pointer to a particular RefCount object. Thus there is no (thread safe)
// way to "demand copy" a RefCount subclass. Trust me; it's been tried. Don't.
//

#if !defined(DEBUG_REFCOUNTS)
# define DEBUG_REFCOUNTS 0
#endif


//
// Base class for reference counted objects
//
class RefCount {  
public:
      RefCount() : mRefCount(0) { }

protected:
      template <class T> friend class RefPointer;

      void ref() const              { ++mRefCount; }
      unsigned int unref() const    { return --mRefCount; }
      
      // if you call this for anything but debug output, you will go to hell
      // (free handbasket included)
      unsigned int refCountForDebuggingOnly() const { return mRefCount; }

private:
    mutable AtomicCounter<unsigned int> mRefCount;
};


//
// A pointer type supported by reference counts.
// T must be derived from RefCount.
//
template <class T>
class RefPointer {
      template <class Sub> friend class RefPointer; // share with other instances
public:
      RefPointer() : ptr(0) {}                  // default to NULL pointer
      RefPointer(const RefPointer& p) { if (p) p->ref(); ptr = p.ptr; }
      RefPointer(T *p) { if (p) p->ref(); ptr = p; }
      
      template <class Sub>
      RefPointer(const RefPointer<Sub>& p) { if (p) p->ref(); ptr = p.ptr; }
    
      ~RefPointer() { release(); }

      RefPointer& operator = (const RefPointer& p)    { setPointer(p.ptr); return *this; }
      RefPointer& operator = (T * p)                              { setPointer(p); return *this; }

      template <class Sub>
      RefPointer& operator = (const RefPointer<Sub>& p) { setPointer(p.ptr); return *this; }

      // dereference operations
    T* get () const                       { _check(); return ptr; }     // mimic auto_ptr
      operator T * () const         { _check(); return ptr; }
      T * operator -> () const      { _check(); return ptr; }
      T & operator * () const       { _check(); return *ptr; }

protected:
      void release() { if (ptr && ptr->unref() == 0) delete ptr; }
      void setPointer(T *p) { if (p) p->ref(); release(); ptr = p; }
      
#if defined(NDEBUG) || !DEBUG_REFCOUNTS
      void _check() const { }
#else
      void _check() const { assert(!ptr || ptr->refCountForDebuggingOnly()); }
#endif //NDEBUG

      T *ptr;
};

template <class T>
bool operator <(const RefPointer<T> &r1, const RefPointer<T> &r2)
{
      T *p1 = r1.get(), *p2 = r2.get();
      return p1 && p2 ? *p1 < *p2 : p1 < p2;
}

template <class T>
bool operator ==(const RefPointer<T> &r1, const RefPointer<T> &r2)
{
      T *p1 = r1.get(), *p2 = r2.get();
      return p1 && p2 ? *p1 == *p2 : p1 == p2;
}

template <class T>
bool operator !=(const RefPointer<T> &r1, const RefPointer<T> &r2)
{
      T *p1 = r1.get(), *p2 = r2.get();
      return p1 && p2 ? *p1 != *p2 : p1 != p2;
}

} // end namespace Security

#endif // !_SECURITY_REFCOUNT_H_

Generated by  Doxygen 1.6.0   Back to index