|
reSIProcate/rutil
9694
|
00001 #if !defined(RESIP_SHAREDPTR_HXX) 00002 #define RESIP_SHAREDPTR_HXX 00003 00013 #include "rutil/SharedCount.hxx" 00014 #include <memory> // for std::auto_ptr 00015 #include <algorithm> // for std::swap 00016 #include <functional> // for std::less 00017 #include <typeinfo> // for std::bad_cast 00018 #include <iosfwd> // for std::basic_ostream 00019 #include <cassert> 00020 00021 namespace resip 00022 { 00023 00024 template<class T> class enable_shared_from_this; 00025 00026 struct static_cast_tag {}; 00027 struct const_cast_tag {}; 00028 struct dynamic_cast_tag {}; 00029 struct polymorphic_cast_tag {}; 00030 00031 template<class T> struct SharedPtr_traits 00032 { 00033 typedef T & reference; 00034 }; 00035 00036 template<> struct SharedPtr_traits<void> 00037 { 00038 typedef void reference; 00039 }; 00040 00041 template<> struct SharedPtr_traits<void const> 00042 { 00043 typedef void reference; 00044 }; 00045 00046 template<> struct SharedPtr_traits<void volatile> 00047 { 00048 typedef void reference; 00049 }; 00050 00051 template<> struct SharedPtr_traits<void const volatile> 00052 { 00053 typedef void reference; 00054 }; 00055 00056 // enable_shared_from_this support 00057 00058 template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, resip::enable_shared_from_this<T> const * pe, Y const * px ) 00059 { 00060 if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn); 00061 } 00062 00063 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) 00064 { 00065 } 00066 00073 template<class T> class SharedPtr 00074 { 00075 private: 00076 00077 // Borland 5.5.1 specific workaround 00078 typedef SharedPtr<T> this_type; 00079 00080 public: 00081 00082 typedef T element_type; 00083 typedef T value_type; 00084 typedef T * pointer; 00085 typedef typename SharedPtr_traits<T>::reference reference; 00086 00087 SharedPtr(): px(0), pn() // never throws in 1.30+ 00088 { 00089 } 00090 00091 template<class Y> 00092 explicit SharedPtr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete 00093 { 00094 sp_enable_shared_from_this( pn, p, p ); 00095 } 00096 00097 // 00098 // Requirements: D's copy constructor must not throw 00099 // 00100 // SharedPtr will release p by calling d(p) 00101 // 00102 00103 template<class Y, class D> SharedPtr(Y * p, D d): px(p), pn(p, d) 00104 { 00105 sp_enable_shared_from_this( pn, p, p ); 00106 } 00107 00108 // generated copy constructor, assignment, destructor are fine... 00109 00110 // except that Borland C++ has a bug, and g++ with -Wsynth warns 00111 #if defined(__BORLANDC__) || defined(__GNUC__) 00112 SharedPtr & operator=(SharedPtr const & r) // never throws 00113 { 00114 px = r.px; 00115 pn = r.pn; // shared_count::op= doesn't throw 00116 return *this; 00117 } 00118 #endif 00119 00120 template<class Y> 00121 SharedPtr(SharedPtr<Y> const & r): px(r.px), pn(r.pn) // never throws 00122 { 00123 } 00124 00125 template<class Y> 00126 SharedPtr(SharedPtr<Y> const & r, static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) 00127 { 00128 } 00129 00130 template<class Y> 00131 SharedPtr(SharedPtr<Y> const & r, const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn) 00132 { 00133 } 00134 00135 template<class Y> 00136 SharedPtr(SharedPtr<Y> const & r, dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) 00137 { 00138 if(px == 0) // need to allocate new counter -- the cast failed 00139 { 00140 pn = resip::shared_count(); 00141 } 00142 } 00143 00144 template<class Y> 00145 SharedPtr(SharedPtr<Y> const & r, polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) 00146 { 00147 if(px == 0) 00148 { 00149 throw std::bad_cast(); 00150 } 00151 } 00152 00153 template<class Y> 00154 explicit SharedPtr(std::auto_ptr<Y> & r): px(r.get()), pn() 00155 { 00156 Y * tmp = r.get(); 00157 pn = shared_count(r); 00158 sp_enable_shared_from_this( pn, tmp, tmp ); 00159 } 00160 00161 template<class Y> 00162 SharedPtr & operator=(SharedPtr<Y> const & r) // never throws 00163 { 00164 px = r.px; 00165 pn = r.pn; // shared_count::op= doesn't throw 00166 return *this; 00167 } 00168 00169 template<class Y> 00170 SharedPtr & operator=(std::auto_ptr<Y> & r) 00171 { 00172 this_type(r).swap(*this); 00173 return *this; 00174 } 00175 00176 void reset() // never throws in 1.30+ 00177 { 00178 this_type().swap(*this); 00179 } 00180 00181 template<class Y> void reset(Y * p) // Y must be complete 00182 { 00183 assert(p == 0 || p != px); // catch self-reset errors 00184 this_type(p).swap(*this); 00185 } 00186 00187 template<class Y, class D> void reset(Y * p, D d) 00188 { 00189 this_type(p, d).swap(*this); 00190 } 00191 00192 reference operator* () const // never throws 00193 { 00194 assert(px != 0); 00195 return *px; 00196 } 00197 00198 T * operator-> () const // never throws 00199 { 00200 assert(px != 0); 00201 return px; 00202 } 00203 00204 T * get() const // never throws 00205 { 00206 return px; 00207 } 00208 00209 // implicit conversion to "bool" 00210 #if defined(__SUNPRO_CC) // BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) 00211 operator bool () const 00212 { 00213 return px != 0; 00214 } 00215 #elif defined(__MWERKS__) // BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) 00216 typedef T * (this_type::*unspecified_bool_type)() const; 00217 operator unspecified_bool_type() const // never throws 00218 { 00219 return px == 0? 0: &this_type::get; 00220 } 00221 #else 00222 typedef T * this_type::*unspecified_bool_type; 00223 operator unspecified_bool_type() const // never throws 00224 { 00225 return px == 0? 0: &this_type::px; 00226 } 00227 #endif 00228 00229 // operator! is redundant, but some compilers need it 00230 bool operator! () const // never throws 00231 { 00232 return px == 0; 00233 } 00234 00235 bool unique() const // never throws 00236 { 00237 return pn.unique(); 00238 } 00239 00240 long use_count() const // never throws 00241 { 00242 return pn.use_count(); 00243 } 00244 00245 void swap(SharedPtr<T> & other) // never throws 00246 { 00247 std::swap(px, other.px); 00248 pn.swap(other.pn); 00249 } 00250 00251 template<class Y> bool _internal_less(SharedPtr<Y> const & rhs) const 00252 { 00253 return pn < rhs.pn; 00254 } 00255 00256 void * _internal_get_deleter(std::type_info const & ti) const 00257 { 00258 return pn.get_deleter(ti); 00259 } 00260 00261 // Tasteless as this may seem, making all members public allows member templates 00262 // to work in the absence of member template friends. (Matthew Langston) 00263 00264 private: 00265 00266 template<class Y> friend class SharedPtr; 00267 00268 T * px; // contained pointer 00269 shared_count pn; // reference counter 00270 00271 }; // SharedPtr 00272 00273 template<class T, class U> inline bool operator==(SharedPtr<T> const & a, SharedPtr<U> const & b) 00274 { 00275 return a.get() == b.get(); 00276 } 00277 00278 template<class T, class U> inline bool operator!=(SharedPtr<T> const & a, SharedPtr<U> const & b) 00279 { 00280 return a.get() != b.get(); 00281 } 00282 00283 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 00284 00285 // Resolve the ambiguity between our op!= and the one in rel_ops 00286 00287 template<class T> inline bool operator!=(SharedPtr<T> const & a, SharedPtr<T> const & b) 00288 { 00289 return a.get() != b.get(); 00290 } 00291 00292 #endif 00293 00294 template<class T, class U> inline bool operator<(SharedPtr<T> const & a, SharedPtr<U> const & b) 00295 { 00296 return a._internal_less(b); 00297 } 00298 00299 template<class T> inline void swap(SharedPtr<T> & a, SharedPtr<T> & b) 00300 { 00301 a.swap(b); 00302 } 00303 00304 template<class T, class U> SharedPtr<T> static_pointer_cast(SharedPtr<U> const & r) 00305 { 00306 return SharedPtr<T>(r, static_cast_tag()); 00307 } 00308 00309 template<class T, class U> SharedPtr<T> const_pointer_cast(SharedPtr<U> const & r) 00310 { 00311 return SharedPtr<T>(r, const_cast_tag()); 00312 } 00313 00314 template<class T, class U> SharedPtr<T> dynamic_pointer_cast(SharedPtr<U> const & r) 00315 { 00316 return SharedPtr<T>(r, dynamic_cast_tag()); 00317 } 00318 00319 // shared_*_cast names are deprecated. Use *_pointer_cast instead. 00320 00321 template<class T, class U> SharedPtr<T> shared_static_cast(SharedPtr<U> const & r) 00322 { 00323 return SharedPtr<T>(r, static_cast_tag()); 00324 } 00325 00326 template<class T, class U> SharedPtr<T> shared_dynamic_cast(SharedPtr<U> const & r) 00327 { 00328 return SharedPtr<T>(r, dynamic_cast_tag()); 00329 } 00330 00331 template<class T, class U> SharedPtr<T> shared_polymorphic_cast(SharedPtr<U> const & r) 00332 { 00333 return SharedPtr<T>(r, polymorphic_cast_tag()); 00334 } 00335 00336 template<class T, class U> SharedPtr<T> shared_polymorphic_downcast(SharedPtr<U> const & r) 00337 { 00338 assert(dynamic_cast<T *>(r.get()) == r.get()); 00339 return shared_static_cast<T>(r); 00340 } 00341 00342 template<class T> inline T * get_pointer(SharedPtr<T> const & p) 00343 { 00344 return p.get(); 00345 } 00346 00347 // operator<< 00348 #if defined(__GNUC__) && (__GNUC__ < 3) 00349 template<class Y> EncodeStream & operator<< (EncodeStream & os, SharedPtr<Y> const & p) 00350 { 00351 os << p.get(); 00352 return os; 00353 } 00354 #else 00355 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, SharedPtr<Y> const & p) 00356 { 00357 os << p.get(); 00358 return os; 00359 } 00360 #endif 00361 00362 // get_deleter (experimental) 00363 #if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238)) 00364 // g++ 2.9x doesn't allow static_cast<X const *>(void *) 00365 // apparently EDG 2.38 also doesn't accept it 00366 template<class D, class T> D * get_deleter(SharedPtr<T> const & p) 00367 { 00368 void const * q = p._internal_get_deleter(typeid(D)); 00369 return const_cast<D *>(static_cast<D const *>(q)); 00370 } 00371 #else 00372 template<class D, class T> D * get_deleter(SharedPtr<T> const & p) 00373 { 00374 return static_cast<D *>(p._internal_get_deleter(typeid(D))); 00375 } 00376 #endif 00377 00378 } // namespace resip 00379 00380 #endif 00381 00382 // Note: This implementation is a modified version of shared_ptr from 00383 // Boost.org 00384 // 00385 // http://www.boost.org/libs/smart_ptr/shared_ptr.htm 00386 // 00387 00388 /* ==================================================================== 00389 * 00390 * Boost Software License - Version 1.0 - August 17th, 2003 00391 * 00392 * Permission is hereby granted, free of charge, to any person or organization 00393 * obtaining a copy of the software and accompanying documentation covered by 00394 * this license (the "Software") to use, reproduce, display, distribute, 00395 * execute, and transmit the Software, and to prepare derivative works of the 00396 * Software, and to permit third-parties to whom the Software is furnished to 00397 * do so, all subject to the following: 00398 * 00399 * The copyright notices in the Software and this entire statement, including 00400 * the above license grant, this restriction and the following disclaimer, 00401 * must be included in all copies of the Software, in whole or in part, and 00402 * all derivative works of the Software, unless such copies or derivative 00403 * works are solely in the form of machine-executable object code generated by 00404 * a source language processor. 00405 * 00406 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00407 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00408 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 00409 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 00410 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 00411 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00412 * DEALINGS IN THE SOFTWARE. 00413 * 00414 * ==================================================================== 00415 */ 00416 00417 00418 /* ==================================================================== 00419 * The Vovida Software License, Version 1.0 00420 * 00421 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00422 * 00423 * Redistribution and use in source and binary forms, with or without 00424 * modification, are permitted provided that the following conditions 00425 * are met: 00426 * 00427 * 1. Redistributions of source code must retain the above copyright 00428 * notice, this list of conditions and the following disclaimer. 00429 * 00430 * 2. Redistributions in binary form must reproduce the above copyright 00431 * notice, this list of conditions and the following disclaimer in 00432 * the documentation and/or other materials provided with the 00433 * distribution. 00434 * 00435 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00436 * and "Vovida Open Communication Application Library (VOCAL)" must 00437 * not be used to endorse or promote products derived from this 00438 * software without prior written permission. For written 00439 * permission, please contact vocal@vovida.org. 00440 * 00441 * 4. Products derived from this software may not be called "VOCAL", nor 00442 * may "VOCAL" appear in their name, without prior written 00443 * permission of Vovida Networks, Inc. 00444 * 00445 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00446 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00447 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00448 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00449 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00450 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00451 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00452 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00453 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00454 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00455 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00456 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00457 * DAMAGE. 00458 * 00459 * ==================================================================== 00460 * 00461 * This software consists of voluntary contributions made by Vovida 00462 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00463 * Inc. For more information on Vovida Networks, Inc., please see 00464 * <http://www.vovida.org/>. 00465 * 00466 */
1.7.5.1