00001 00004 /* Copyright 1999,2000,2001 BrightStation PLC 00005 * Copyright 2002 Ananova Ltd 00006 * Copyright 2002,2003,2004,2007 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 00021 * USA 00022 */ 00023 00024 #ifndef XAPIAN_INCLUDED_BASE_H 00025 #define XAPIAN_INCLUDED_BASE_H 00026 00027 #include <xapian/deprecated.h> 00028 00029 namespace Xapian { 00030 namespace Internal { 00031 00036 class RefCntBase { 00037 /* Note: We never delete a pointer to a subclass of RefCntBase using 00038 * a RefCntBase *, so we don't need a virtual destructor here. 00039 */ 00040 protected: 00048 RefCntBase(const RefCntBase &) : ref_count(0) { } 00049 00050 public: 00052 RefCntBase() : ref_count(0) { } 00053 00054 typedef unsigned int ref_count_t; 00055 00059 mutable ref_count_t ref_count; 00060 }; 00061 00066 template <class T> 00067 class RefCntPtr { 00068 private: 00069 T *dest; 00070 00071 public: 00072 T *operator->() const; 00073 T &operator*() const; 00074 T *get() const; 00083 RefCntPtr(T *dest_); 00084 RefCntPtr(); 00085 RefCntPtr(const RefCntPtr &other); 00086 void operator=(const RefCntPtr &other); 00087 void operator=(T *dest_); 00088 ~RefCntPtr(); 00089 00090 template <class U> 00091 RefCntPtr(const RefCntPtr<U> &other); 00092 }; 00093 00094 template <class T> 00095 inline RefCntPtr<T>::RefCntPtr(T *dest_) : dest(dest_) 00096 { 00097 if (dest) ++dest->ref_count; 00098 } 00099 00100 template <class T> 00101 inline RefCntPtr<T>::RefCntPtr() : dest(0) 00102 { 00103 } 00104 00105 template <class T> 00106 inline RefCntPtr<T>::RefCntPtr(const RefCntPtr &other) : dest(other.dest) 00107 { 00108 if (dest) ++dest->ref_count; 00109 } 00110 00111 template <class T> 00112 inline void RefCntPtr<T>::operator=(const RefCntPtr &other) { 00113 operator=(other.dest); 00114 } 00115 00116 template <class T> 00117 inline void RefCntPtr<T>::operator=(T *dest_) { 00118 // copy the new dest in before we delete the old to avoid a small 00119 // window in which dest points to a deleted object 00120 // FIXME: if pointer assignment isn't atomic, we ought to use locking... 00121 T *old_dest = dest; 00122 dest = dest_; 00123 // Increment the new before we decrement the old so that if dest == dest_ 00124 // we don't delete the pointer. 00125 // 00126 // Note that if dest == dest_, either both are NULL (in which case we 00127 // aren't reference counting), or we're already reference counting the 00128 // object, in which case ref_count is non-zero at this point. So we 00129 // won't accidentally delete an untracked object by doing this. 00130 if (dest) ++dest->ref_count; 00131 if (old_dest && --old_dest->ref_count == 0) delete old_dest; 00132 } 00133 00134 template <class T> 00135 inline RefCntPtr<T>::~RefCntPtr() 00136 { 00137 if (dest && --dest->ref_count == 0) { 00138 // zero before we delete to avoid a small window in which dest points 00139 // to a deleted object 00140 // FIXME: if pointer assignment isn't atomic, we ought to use locking... 00141 T * condemned = dest; 00142 dest = 0; 00143 delete condemned; 00144 } 00145 } 00146 00147 template <class T> 00148 template <class U> 00149 inline 00150 RefCntPtr<T>::RefCntPtr(const RefCntPtr<U> &other) 00151 : dest(other.get()) 00152 { 00153 if (dest) ++dest->ref_count; 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>::operator*() const 00164 { 00165 return *dest; 00166 } 00167 00168 template <class T> 00169 inline T *RefCntPtr<T>::get() const 00170 { 00171 return dest; 00172 } 00173 00174 } 00175 } 00176 00177 #endif /* XAPIAN_INCLUDED_BASE_H */