sharedptr.h

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2011 by the FIFE team                              *
00003  *   http://www.fifengine.net                                              *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 #ifndef FIFE_SHARED_PTR_H_
00022 #define FIFE_SHARED_PTR_H_
00023 
00024 // Standard C++ library includes
00025 #include <cassert>
00026 #include <functional>
00027 
00028 // 3rd party library includes
00029 
00030 // FIFE includes
00031 // These includes are split up in two parts, separated by one empty line
00032 // First block: files included from the FIFE root src directory
00033 // Second block: files included from the same folder
00034 #include "fife_stdint.h"
00035 
00036 namespace FIFE {
00041     template <typename T>
00042     class SharedPtr {
00043     public:
00044 
00049         SharedPtr()
00050         : m_ptr(0), m_refCount(0) {
00051 
00052         }
00053 
00059         template <typename U>
00060         explicit SharedPtr(U *ptr)
00061         : m_ptr(ptr), m_refCount(ptr ? new uint32_t(1) : 0) {
00062 
00063         }
00064 
00068         SharedPtr(const SharedPtr& rhs)
00069         : m_ptr(rhs.m_ptr), m_refCount(rhs.m_refCount) {
00070             // increase reference count
00071             incRefCount();
00072         }
00073 
00079         template <typename U>
00080         SharedPtr(const SharedPtr<U>& rhs) {
00081             m_ptr = rhs.get();
00082             m_refCount = rhs.useCountPtr();
00083             incRefCount();
00084         }
00085 
00090         ~SharedPtr() {
00091             // decrement reference count
00092             decRefCount();
00093 
00094             // check to see if we need to delete
00095             if (m_refCount && *m_refCount == 0) {
00096                 // delete and set pointers to null
00097                 delete m_ptr;
00098                 delete m_refCount;
00099                 m_ptr = 0;
00100                 m_refCount = 0;
00101             }
00102         }
00103 
00106         SharedPtr& operator=(const SharedPtr& rhs) {
00107             // handle self assignment
00108             if (rhs.get() == m_ptr) {
00109                 return *this;
00110             }
00111 
00112             // store in temporary (which causes a ref count increase)
00113             // and swap with this object
00114             SharedPtr<T> temp(rhs);
00115             swap(temp);
00116             return *this;
00117         }
00118 
00123         template <typename U>
00124         SharedPtr& operator=(const SharedPtr<U>& rhs) {
00125             // handle self assignment
00126             if (rhs.get() == m_ptr) {
00127                 return *this;
00128             }
00129 
00130             // store in temporary (which causes a ref count increase)
00131             // and swap with this object
00132             SharedPtr<T> temp(rhs);
00133             swap(temp);
00134             return *this;
00135         }
00136 
00140         inline T& operator*() const {
00141             assert(m_ptr);
00142             return *m_ptr;
00143         }
00144 
00148         inline T* operator->() const {
00149             assert(m_ptr);
00150             return m_ptr;
00151         }
00152 
00155         inline T* get() const {
00156             return m_ptr;
00157         }
00158 
00164         inline void reset(T* ptr = 0) {
00165             assert(ptr == 0 || ptr != m_ptr);
00166             SharedPtr<T>(ptr).swap(*this);
00167         }
00168 
00173         inline uint32_t useCount() const {
00174             assert(m_refCount);
00175 
00176             if (!m_refCount) {
00177                 return 0;
00178             }
00179 
00180             return *m_refCount;
00181         }
00182 
00187         inline uint32_t* useCountPtr() const {
00188             return m_refCount;
00189         }
00190 
00197         inline bool unique() const {
00198             assert(m_refCount);
00199             return (*m_refCount == 1);
00200         }
00201 
00207         operator bool() const {
00208             return (m_ptr != 0);
00209         }
00210 
00213         bool operator!() const {
00214             return (m_ptr == 0);
00215         }
00216 
00217     private:
00218 
00222         inline void swap(SharedPtr<T>& rhs) {
00223             std::swap(m_ptr, rhs.m_ptr);
00224             std::swap(m_refCount, rhs.m_refCount);
00225         }
00226 
00230         inline void incRefCount() {
00231             if (m_refCount) {
00232                 ++(*m_refCount);
00233             }
00234         }
00235 
00239         inline void decRefCount() {
00240             if (m_refCount) {
00241                 --(*m_refCount);
00242             }
00243         }
00244 
00245     private:
00246         T* m_ptr;
00247         uint32_t* m_refCount;
00248     };
00249 
00252     template <typename T, typename U>
00253     inline bool operator==(const SharedPtr<T>& lhs, const SharedPtr<U>& rhs) {
00254         return (lhs.get() == rhs.get());
00255     }
00256 
00259     template <typename T, typename U>
00260     inline bool operator!=(const SharedPtr<T>& lhs, const SharedPtr<U>& rhs) {
00261         return (lhs.get() != rhs.get());
00262     }
00263 
00266     template<class T, class U>
00267     inline bool operator<(SharedPtr<T> const& lhs, SharedPtr<U> const& rhs) {
00268         return std::less<const void*>()(lhs.get(), rhs.get());
00269     }
00270 
00274     template <typename T>
00275     SharedPtr<T> make_shared(T* ptr) {
00276         return SharedPtr<T>(ptr);
00277     }
00278 } //FIFE
00279 
00280 #endif //FIFE_SHARED_PTR_H_