# include/xapian/base.h

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