# refcounted.h

Go to the documentation of this file.

    00001
    00002
    00003
    00004 /***********************************************************************
    00005  Copyright (c) 2007 by Educational Technology Resources, Inc. and
    00006  (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
    00007  code in this file.  See the CREDITS.txt file in the top directory
    00008  of the distribution for details.
    00009
    00010  This file is part of MySQL++.
    00011
    00012  MySQL++ is free software; you can redistribute it and/or modify it
    00013  under the terms of the GNU Lesser General Public License as published
    00014  by the Free Software Foundation; either version 2.1 of the License, or
    00015  (at your option) any later version.
    00016
    00017  MySQL++ is distributed in the hope that it will be useful, but WITHOUT
    00018  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    00019  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
    00020  License for more details.
    00021
    00022  You should have received a copy of the GNU Lesser General Public
    00023  License along with MySQL++; if not, write to the Free Software
    00024  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
    00025  USA
    00026 ***********************************************************************/
    00027
    00028 #if !defined(MYSQLPP_REFCOUNTED_H)
    00029 #define MYSQLPP_REFCOUNTED_H
    00030
    00031 #include <memory>
    00032
    00033 namespace mysqlpp {
    00034
    00042 template <class T>
    00043 struct RefCountedPointerDestroyer
    00044 {
    00046         void operator()(T* doomed) const { delete doomed; }
    00047 };
    00048
    00049
    00076
    00077 template <class T, class Destroyer = RefCountedPointerDestroyer<T> >
    00078 class RefCountedPointer
    00079 {
    00080 public:
    00081         typedef RefCountedPointer<T> ThisType;
    00082
    00087         RefCountedPointer() :
    00088         counted_(0),
    00089         refs_(0)
    00090         {
    00091         }
    00092
    00098         explicit RefCountedPointer(T* c) :
    00099         counted_(c),
    00100         refs_(0)
    00101         {
    00102                 std::auto_ptr<T> exception_guard(counted_);
    00103                 if (counted_) {
    00104                         refs_ = new size_t(1);
    00105                 }
    00106                 exception_guard.release();      // previous new didn't throw
    00107         }
    00108
    00110         RefCountedPointer(const ThisType& other) :
    00111         counted_(other.counted_),
    00112         refs_(other.counted_ ? other.refs_ : 0)
    00113         {
    00114                 if (counted_) {
    00115                         ++(*refs_);
    00116                 }
    00117         }
    00118
    00123         ~RefCountedPointer()
    00124         {
    00125                 if (refs_ && (--(*refs_) == 0)) {
    00126                         Destroyer()(counted_);
    00127                         delete refs_;
    00128                 }
    00129         }
    00130
    00138         ThisType& assign(T* c)
    00139         {
    00140                 // The create-temporary-and-swap idiom lets us keep memory
    00141                 // allocation in the ctor and deallocation in the dtor so
    00142                 // we don't leak in the face of an exception.
    00143                 ThisType(c).swap(*this);
    00144                 return *this;
    00145         }
    00146
    00155         ThisType& assign(const ThisType& other)
    00156         {
    00157                 // The create-temporary-and-swap idiom lets us keep memory
    00158                 // allocation in the ctor and deallocation in the dtor so
    00159                 // we don't leak in the face of an exception.
    00160                 ThisType(other).swap(*this);
    00161                 return *this;
    00162         }
    00163
    00168         ThisType& operator =(T* c)
    00169         {
    00170                 return assign(c);
    00171         }
    00172
    00178         ThisType& operator =(const ThisType& rhs)
    00179         {
    00180                 return assign(rhs);
    00181         }
    00182
    00184         T* operator ->() const
    00185         {
    00186                 return counted_;
    00187         }
    00188
    00190         T& operator *() const
    00191         {
    00192                 return *counted_;
    00193         }
    00194
    00214         operator void*()
    00215         {
    00216                 return counted_;
    00217         }
    00218
    00222         operator const void*() const
    00223         {
    00224                 return counted_;
    00225         }
    00226
    00228         T* raw()
    00229         {
    00230                 return counted_;
    00231         }
    00232
    00234         const T* raw() const
    00235         {
    00236                 return counted_;
    00237         }
    00238
    00243         void swap(ThisType& other)
    00244         {
    00245                 std::swap(counted_, other.counted_);
    00246                 std::swap(refs_, other.refs_);
    00247         }
    00248
    00249 private:
    00251         T* counted_;
    00252
    00258         size_t* refs_;
    00259 };
    00260
    00261
    00262 } // end namespace mysqlpp
    00263
    00264 #endif // !defined(MYSQLPP_REFCOUNTED_H)
    00265