# 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 #include <xapian/deprecated.h>
    00029
    00030 namespace Xapian {
    00031 namespace Internal {
    00032
    00037 class RefCntBase {
    00038     protected:
    00046         RefCntBase(const RefCntBase &) : ref_count(0) { }
    00047
    00048     public:
    00050         RefCntBase() : ref_count(0) { }
    00051
    00052         typedef unsigned int ref_count_t;
    00053
    00057         mutable ref_count_t ref_count;
    00058 };
    00059
    00064 template <class T>
    00065 class RefCntPtr {
    00066     private:
    00067         T *dest;
    00068
    00069     public:
    00070         T *operator->() const;
    00071         T &operator*() const;
    00072         T *get() const;
    00081         RefCntPtr(T *dest_);
    00082         RefCntPtr();
    00083         RefCntPtr(const RefCntPtr &other);
    00084         void operator=(const RefCntPtr &other);
    00085         void operator=(T *dest_);
    00086         ~RefCntPtr();
    00087
    00088         template <class U>
    00089         RefCntPtr(const RefCntPtr<U> &other);
    00090 };
    00091
    00092 template <class T>
    00093 inline RefCntPtr<T>::RefCntPtr(T *dest_) : dest(dest_)
    00094 {
    00095     if (dest) ++dest->ref_count;
    00096 }
    00097
    00098 template <class T>
    00099 inline RefCntPtr<T>::RefCntPtr() : dest(0)
    00100 {
    00101 }
    00102
    00103 template <class T>
    00104 inline RefCntPtr<T>::RefCntPtr(const RefCntPtr &other) : dest(other.dest)
    00105 {
    00106     if (dest) ++dest->ref_count;
    00107 }
    00108
    00109 template <class T>
    00110 inline void RefCntPtr<T>::operator=(const RefCntPtr &other) {
    00111     operator=(other.dest);
    00112 }
    00113
    00114 template <class T>
    00115 inline void RefCntPtr<T>::operator=(T *dest_) {
    00116     // check if we're assigning a pointer to itself
    00117     if (dest == dest_) return;
    00118
    00119     // copy the new dest in before we delete the old to avoid a small
    00120     // window in which dest points to a deleted object
    00121     // FIXME: if pointer assignment isn't atomic, we ought to use locking...
    00122     T *old_dest = dest;
    00123     dest = dest_;
    00124     if (dest) ++dest->ref_count;
    00125     if (old_dest && --old_dest->ref_count == 0) delete old_dest;
    00126 }
    00127
    00128 template <class T>
    00129 inline RefCntPtr<T>::~RefCntPtr()
    00130 {
    00131     if (dest && --dest->ref_count == 0) {
    00132         // zero before we delete to avoid a small window in which dest points
    00133         // to a deleted object
    00134         // FIXME: if pointer assignment isn't atomic, we ought to use locking...
    00135         T * condemned = dest;
    00136         dest = 0;
    00137         delete condemned;
    00138     }
    00139 }
    00140
    00141 template <class T>
    00142 template <class U>
    00143 inline
    00144 RefCntPtr<T>::RefCntPtr(const RefCntPtr<U> &other)
    00145         : dest(other.get())
    00146 {
    00147     if (dest) ++dest->ref_count;
    00148 }
    00149
    00150 template <class T>
    00151 inline T *RefCntPtr<T>::operator->() const
    00152 {
    00153     return dest;
    00154 }
    00155
    00156 template <class T>
    00157 inline T &RefCntPtr<T>::operator*() const
    00158 {
    00159     return *dest;
    00160 }
    00161
    00162 template <class T>
    00163 inline T *RefCntPtr<T>::get() const
    00164 {
    00165     return dest;
    00166 }
    00167
    00168 }
    00169 }
    00170
    00171 #endif /* XAPIAN_INCLUDED_BASE_H */