include/xapian/base.h

Go to the documentation of this file.
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 */

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.