# include/xapian/base.h

    00001 /* base.h: Reference-counted pointers
    00002  *
    00003  * ----START-LICENCE----
    00004  * Copyright 1999,2000,2001 BrightStation PLC
    00005  * Copyright 2002 Ananova Ltd
    00006  * Copyright 2002,2003,2004 Olly Betts
    00007  *
    00008  * This program is free software; you can redistribute it and/or
    00009  * modify it under the terms of the GNU General Public License as
    00010  * published by the Free Software Foundation; either version 2 of the
    00011  * License, or (at your option) any later version.
    00012  *
    00013  * This program is distributed in the hope that it will be useful,
    00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00016  * GNU General Public License for more details.
    00017  *
    00018  * You should have received a copy of the GNU General Public License
    00019  * along with this program; if not, write to the Free Software
    00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    00021  * USA
    00022  * -----END-LICENCE-----
    00023  */
    00024
    00025 #ifndef XAPIAN_INCLUDED_BASE_H
    00026 #define XAPIAN_INCLUDED_BASE_H
    00027
    00028 namespace Xapian {
    00029 namespace Internal {
    00030
    00035 class RefCntBase {
    00036     protected:
    00044         RefCntBase(const RefCntBase &) : ref_count(0) { }
    00045
    00046     public:
    00048         RefCntBase() : ref_count(0) { }
    00049
    00050         typedef unsigned int ref_count_t;
    00051
    00055         mutable ref_count_t ref_count;
    00056 };
    00057
    00062 template <class T>
    00063 class RefCntPtr {
    00064     private:
    00065         T *dest;
    00066
    00067     public:
    00068         T *operator->() const;
    00069         T &operator*() const;
    00070         T *get() const;
    00079         RefCntPtr(T *dest_);
    00080         RefCntPtr();
    00081         RefCntPtr(const RefCntPtr &other);
    00082         void operator=(const RefCntPtr &other);
    00083         void operator=(T *dest_);
    00084         ~RefCntPtr();
    00085
    00086         template <class U>
    00087         RefCntPtr(const RefCntPtr<U> &other);
    00088 };
    00089
    00090 template <class T>
    00091 inline RefCntPtr<T>::RefCntPtr(T *dest_) : dest(dest_)
    00092 {
    00093     if (dest) ++dest->ref_count;
    00094 }
    00095
    00096 template <class T>
    00097 inline RefCntPtr<T>::RefCntPtr() : dest(0)
    00098 {
    00099 }
    00100
    00101 template <class T>
    00102 inline RefCntPtr<T>::RefCntPtr(const RefCntPtr &other) : dest(other.dest)
    00103 {
    00104     if (dest) ++dest->ref_count;
    00105 }
    00106
    00107 template <class T>
    00108 inline void RefCntPtr<T>::operator=(const RefCntPtr &other) {
    00109     operator=(other.dest);
    00110 }
    00111
    00112 template <class T>
    00113 inline void RefCntPtr<T>::operator=(T *dest_) {
    00114     // check if we're assigning a pointer to itself
    00115     if (dest == dest_) return;
    00116
    00117     // copy the new dest in before we delete the old to avoid a small
    00118     // window in which dest points to a deleted object
    00119     // FIXME: if pointer assignment isn't atomic, we ought to use locking...
    00120     T *old_dest = dest;
    00121     dest = dest_;
    00122     if (dest) ++dest->ref_count;
    00123     if (old_dest && --old_dest->ref_count == 0) delete old_dest;
    00124 }
    00125
    00126 template <class T>
    00127 inline RefCntPtr<T>::~RefCntPtr()
    00128 {
    00129     if (dest && --dest->ref_count == 0) {
    00130         // zero before we delete to avoid a small window in which dest points
    00131         // to a deleted object
    00132         // FIXME: if pointer assignment isn't atomic, we ought to use locking...
    00133         T * condemned = dest;
    00134         dest = 0;
    00135         delete condemned;
    00136     }
    00137 }
    00138
    00139 template <class T>
    00140 template <class U>
    00141 inline
    00142 RefCntPtr<T>::RefCntPtr(const RefCntPtr<U> &other)
    00143         : dest(other.get())
    00144 {
    00145     if (dest) ++dest->ref_count;
    00146 }
    00147
    00148 template <class T>
    00149 inline T *RefCntPtr<T>::operator->() const
    00150 {
    00151     return dest;
    00152 }
    00153
    00154 template <class T>
    00155 inline T &RefCntPtr<T>::operator*() const
    00156 {
    00157     return *dest;
    00158 }
    00159
    00160 template <class T>
    00161 inline T *RefCntPtr<T>::get() const
    00162 {
    00163     return dest;
    00164 }
    00165
    00166 }
    00167 }
    00168
    00169 #endif /* XAPIAN_INCLUDED_BASE_H */