00001 ////////////////////////////////////////////////////////////////////// 00002 // Copyright (c) 2001-2002 David Pritchard <drpritch@alumni.uwaterloo.ca> 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either 00007 // version 2 of the License, or (at your option) any later 00008 // version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 #ifndef freecloth_resmgt_rcProxyShdPtr_h 00020 #define freecloth_resmgt_rcProxyShdPtr_h 00021 00022 #ifndef freecloth_resmgt_package_h 00023 #include <freecloth/resmgt/package.h> 00024 #endif 00025 00026 #ifndef freecloth_base_typeinfo 00027 #include <freecloth/base/typeinfo> 00028 #endif 00029 00030 FREECLOTH_NAMESPACE_START 00031 00032 //////////////////////////////////////////////////////////////////////////////// 00033 // FORWARD DECLARATIONS 00034 00035 template <class T> 00036 class RCProxyShdPtr; 00037 00038 //////////////////////////////////////////////////////////////////////////////// 00039 /*! 00040 * \class RCProxyShdPtrBase freecloth/resmgt/rcProxyShdPtr.h 00041 * \brief Base class for reference counted smart pointer proxy. 00042 * 00043 * This is not intended for general use. Use RCProxyShdPtr. 00044 */ 00045 class RCProxyShdPtrBase 00046 { 00047 protected: 00048 //----- classes ----- 00049 class Data; 00050 //----- member functions ----- 00051 RCProxyShdPtrBase(); 00052 00053 public: 00054 // FIXME: g++ doesn't like templated friends. Must use this as a 00055 // substitute for now. 00056 00057 //----- data members ----- 00058 Data* _data; 00059 00060 }; 00061 00062 //////////////////////////////////////////////////////////////////////////////// 00063 /*! 00064 * \class RCProxyShdPtrBase::Data freecloth/resmgt/rcProxyShdPtr.h 00065 * \brief Internal data for RCProxyShdPtrBase. 00066 */ 00067 class RCProxyShdPtrBase::Data 00068 { 00069 public: 00070 //----- member functions ----- 00071 Data( void* ptr = 0, UInt32 count = 1 ); 00072 00073 //----- data members ----- 00074 void* _ptr; 00075 UInt32 _count; 00076 }; 00077 00078 //////////////////////////////////////////////////////////////////////////////// 00079 /*! 00080 * \class RCProxyShdPtr freecloth/resmgt/rcProxyShdPtr.h 00081 * \brief Reference-counted shared smart pointer for non-RCBase objects. 00082 * 00083 * When using external classes, such as the STL or a commercial library, 00084 * it is not possible to change these classes to derive from RCBase, for use 00085 * with RCShdPtr. Instead, RCProxyShdPtr can be used, although it is not 00086 * quite as powerful as RCShdPtr. 00087 */ 00088 00089 // FIXME: separate into RCBase<> and RCProxy<> style for more allocation 00090 // efficiency (a la discreet) 00091 // 00092 // Modelled on Yonat Sharon's code. 00093 template <class T> 00094 class RCProxyShdPtr : public RCProxyShdPtrBase 00095 { 00096 public: 00097 //----- types and enumerations ----- 00098 typedef T element_type; 00099 00100 //----- member functions ----- 00101 explicit RCProxyShdPtr( T* = 0 ); 00102 RCProxyShdPtr( const RCProxyShdPtr& rhs ); 00103 ~RCProxyShdPtr(); 00104 00105 RCProxyShdPtr& operator=( const RCProxyShdPtr& rhs ); 00106 00107 #ifdef HAVE_MEMBER_TEMPLATES 00108 //template <class X> friend class RCProxyShdPtr<X>; 00109 template <class X> 00110 RCProxyShdPtr( const RCProxyShdPtr<X>& rhs ) 00111 { 00112 // verify that X* can be converted to T* (i.e. X* is const T*, or 00113 // T is a base class of X) 00114 X* x; 00115 T* t = x; 00116 00117 acquire( rhs._data ); 00118 } 00119 00120 template <class X> 00121 RCProxyShdPtr& operator=( const RCProxyShdPtr<X>& rhs ) 00122 { 00123 // verify that X* can be converted to T* (i.e. X* is const T*, or 00124 // T is a base class of X) 00125 X* x; 00126 T* t = x; 00127 if ( rhs._data != _data ) { 00128 release(); 00129 acquire( rhs._data ); 00130 } 00131 return *this; 00132 } 00133 template <class X> 00134 bool operator==( const RCProxyShdPtr<X>& rhs ) const 00135 { 00136 return _data == rhs._data; 00137 } 00138 template <class X> 00139 bool operator!=( const RCProxyShdPtr<X>& rhs ) const 00140 { 00141 return _data != rhs._data; 00142 } 00143 #endif 00144 00145 bool isNull() const; 00146 T& operator*() const; 00147 T* operator->() const; 00148 T* get () const; 00149 bool operator==( const RCProxyShdPtr& ) const; 00150 bool operator!=( const RCProxyShdPtr& ) const; 00151 00152 private: 00153 00154 //----- member functions ----- 00155 void acquire( Data* ); 00156 void release(); 00157 }; 00158 00159 //////////////////////////////////////////////////////////////////////////////// 00160 // GLOBAL FUNCTIONS 00161 // 00162 00163 template <class T> 00164 std::ostream& operator<<( std::ostream&, const RCProxyShdPtr<T>& ); 00165 00166 FREECLOTH_NAMESPACE_END 00167 00168 #include <freecloth/resmgt/rcProxyShdPtr.inline.h> 00169 00170 #endif