// -*- C++ -*- /*************************************************************************** * * _smartptr.h - definition of class template shared_ptr and weak_ptr * * $Id: _smartptr.h 590052 2007-10-30 12:44:14Z faridz $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Copyright 2005-2006 Rogue Wave Software. * **************************************************************************/ #ifndef _RWSTD_TR1_SMARTPTR_INCLUDED #define _RWSTD_TR1_SMARTPTR_INCLUDED #include #include #include #include _RWSTD_NAMESPACE (__rw) { struct __rw_ptr_base { __rw_ptr_base () : _C_ref (1), _C_weak_ref (0) { } virtual ~__rw_ptr_base () { #ifdef _RWSTDDEBUG _C_ref = 0xdeadbeefL; _C_weak_ref = 0xdeadbeefL; #endif // _RWSTDDEBUG } virtual void* _C_get_deleter () const { return 0; } long _C_get_ref () { _RWSTD_ATOMIC_PREINCREMENT (_C_ref, false); return _RWSTD_ATOMIC_PREDECREMENT (_C_ref, false); } void _C_inc_ref () { _RWSTD_ATOMIC_PREINCREMENT (_C_ref, false); } void _C_inc_ref_weak () { _RWSTD_ATOMIC_PREINCREMENT (_C_weak_ref, false); } void _C_unref () { const long __ref = _RWSTD_ATOMIC_PREDECREMENT (_C_ref, false); if (0 == __ref) _C_delete (); if (__ref <= 0) { if (0 > _RWSTD_ATOMIC_PREDECREMENT (_C_weak_ref, false)) delete this; else _RWSTD_ATOMIC_PREINCREMENT (_C_weak_ref, false); } } void _C_unref_weak () { if (0 >= _RWSTD_ATOMIC_PREDECREMENT (_C_weak_ref, false)) { if (0 > _RWSTD_ATOMIC_PREDECREMENT (_C_ref, false)) delete this; else _RWSTD_ATOMIC_PREINCREMENT (_C_ref, false); } } private: virtual void _C_delete () = 0; long _C_ref; long _C_weak_ref; }; template struct __rw_ptr_body: __rw_ptr_base { __rw_ptr_body (_TypeU *__ptr) : __rw_ptr_base (), _C_ptr (__ptr) { } protected: _TypeU* const _C_ptr; private: virtual void _C_delete () { delete _C_ptr; } }; template struct __rw_ptr_deleter: __rw_ptr_body<_TypeU> { __rw_ptr_deleter (_TypeU *__ptr, const _Deleter &__del) : __rw_ptr_body<_TypeU>(__ptr), _C_del (__del) { } private: virtual void _C_delete () { _C_del (this->_C_ptr); } virtual void* _C_get_deleter () const { return _RWSTD_CONST_CAST (_Deleter*, &_C_del); } _Deleter _C_del; }; } // namespace __rw _RWSTD_NAMESPACE (std) { _RWSTD_NAMESPACE (tr1) { // 2.2.2 - class bad_weak_ptr struct bad_weak_ptr: _RW::__rw_exception { bad_weak_ptr (): _RW::__rw_exception () { } }; template class weak_ptr; // 2.2.3 - class template shared_ptr template class shared_ptr { // declare every specialization a friend and grant // template members access to _C_ptr template friend class shared_ptr; template friend class weak_ptr; template friend shared_ptr<_TypeU> dynamic_pointer_cast (const shared_ptr<_TypeV>&); typedef _RW::__rw_ptr_base _C_base; _C_base *_C_pbody; _TypeT *_C_ptr; template _EXPLICIT shared_ptr (const shared_ptr<_TypeU> &__rhs, const _TypeT*) : _C_pbody (__rhs._C_pbody) { if (_C_pbody) _C_pbody->_C_inc_ref (); } public: typedef _TypeT element_type; // [2.2.3.1] constructors shared_ptr (): _C_pbody (0), _C_ptr (0) { } template _EXPLICIT shared_ptr (_TypeU *__ptr) : _C_pbody (__ptr ? new _RW::__rw_ptr_body<_TypeU>(__ptr) : 0), _C_ptr (__ptr) { /* empty */ } template shared_ptr (_TypeU *__ptr, _Deleter __del) : _C_pbody (new _RW::__rw_ptr_deleter<_TypeU, _Deleter>(__ptr, __del)), _C_ptr (__ptr) { /* empty */ } shared_ptr (const shared_ptr &__rhs) : _C_pbody (__rhs._C_pbody), _C_ptr (__rhs._C_ptr) { if (_C_pbody) _C_pbody->_C_inc_ref (); } template shared_ptr (const shared_ptr<_TypeU> &__rhs) : _C_pbody (__rhs._C_pbody), _C_ptr (__rhs._C_ptr) { if (_C_pbody) _C_pbody->_C_inc_ref (); } template _EXPLICIT shared_ptr (const weak_ptr<_TypeU> &__rhs) : _C_pbody (__rhs._C_pbody), _C_ptr (__rhs._C_ptr) { if (_C_pbody) { if (0 >= _C_pbody->_C_get_ref ()) throw bad_weak_ptr (); _C_pbody->_C_inc_ref (); } } template _EXPLICIT shared_ptr (auto_ptr<_TypeU>&); // [2.2.3.2] destructor ~shared_ptr () { if (_C_pbody) _C_pbody->_C_unref (); #ifdef _RWSTDDEBUG _C_pbody = (_C_base*)0xdeadbeefL; _C_ptr = (element_type*)0xdeadbeefL; #endif // _RWSTDDEBUG } // [2.2.3.3] assignment shared_ptr& operator= (const shared_ptr &__rhs) { if (__rhs._C_pbody) __rhs._C_pbody->_C_inc_ref (); if (_C_pbody) _C_pbody->_C_unref (); _C_pbody = __rhs._C_pbody; _C_ptr = __rhs._C_ptr; return *this; } template shared_ptr& operator= (const shared_ptr<_TypeU> &__rhs) { _C_is_convertible ((_TypeU*)0); if (__rhs._C_pbody) __rhs._C_pbody->_C_inc_ref (); if (_C_pbody) _C_pbody->_C_unref (); _C_pbody = __rhs._C_pbody; _C_ptr = __rhs._C_ptr; return *this; } template shared_ptr& operator= (auto_ptr<_TypeU> &__rhs) { _RW::__rw_ptr_body<_TypeU>* const __tmp = new _RW::__rw_ptr_body<_TypeU>(__rhs.get ()); if (_C_pbody) _C_pbody->_C_unref (); _C_pbody = __tmp; _C_ptr = __rhs.release (); return *this; } // [2.2.3.4] modifiers void swap (shared_ptr &__other) { _C_base* const __body = _C_pbody; element_type* const __ptr = _C_ptr; _C_pbody = __other._C_pbody; _C_ptr = __other._C_ptr; __other._C_pbody = __body; __other._C_ptr = __ptr; } void reset () { if (_C_pbody) { _C_pbody->_C_unref (); _C_pbody = 0; _C_ptr = 0; } } template void reset (_TypeU *__ptr) { shared_ptr<_TypeU>(__ptr).swap (*this); } template void reset (_TypeU *__ptr, _Deleter __del) { shared_ptr<_TypeU>(__ptr, __del).swap (*this); } // [2.2.3.5] observers element_type* get () const { return _C_ptr; } _TYPENAME _RW::__rw_nonvoid_ref::_C_ref operator*() const { _RWSTD_ASSERT (0 != get ()); return *get (); } element_type* operator->() const { return &**this; } long use_count () const { return _C_pbody ? _C_pbody->_C_get_ref () : 0; } bool unique () const { return 1 == use_count (); } operator bool () const { return 0 != get (); } template _Deleter* _C_get_deleter () const { return _RWSTD_STATIC_CAST (_Deleter*, _C_pbody ? _C_pbody->_C_get_deleter () : 0); } template bool _C_less (const shared_ptr<_TypeU> &__rhs) const { return _C_pbody < __rhs._C_pbody; } private: // helper to check whether one pointer is convertible to another // and to enforce the convertibility requirements static void _C_is_convertible (element_type*) { } }; // 2.2.3.6 - shared_ptr comparisons template inline bool operator== (const shared_ptr<_TypeT> &__lhs, const shared_ptr<_TypeU> &__rhs) { return __lhs.get () == __rhs.get (); } template inline bool operator!= (const shared_ptr<_TypeT> &__lhs, const shared_ptr<_TypeU> &__rhs) { return __lhs.get () != __rhs.get (); } template inline bool operator< (const shared_ptr<_TypeT> &__lhs, const shared_ptr<_TypeU> &__rhs) { return __lhs._C_less (__rhs); } // 2.2.3.8 - shared_ptr specialized algorithms template inline void swap (shared_ptr<_TypeT> &__lhs, shared_ptr<_TypeT> &__rhs) { __lhs.swap (__rhs); } // 2.2.3.9 - shared_ptr casts template inline shared_ptr<_TypeT> static_pointer_cast (const shared_ptr<_TypeU> &__src) { _TypeT* const __ptr = _RWSTD_STATIC_CAST (_TypeT*, __src.get ()); if (__ptr) return shared_ptr<_TypeT>(__src, __ptr); return shared_ptr<_TypeT>(); } template inline shared_ptr<_TypeT> dynamic_pointer_cast (const shared_ptr<_TypeU> &__src) { _TypeT* const __ptr = _RWSTD_DYNAMIC_CAST (_TypeT*, __src.get ()); if (__ptr) return shared_ptr<_TypeT>(__src, __ptr); return shared_ptr<_TypeT>(); } template inline shared_ptr<_TypeT> const_pointer_cast (const shared_ptr<_TypeU> &__src) { _TypeT* const __ptr = _RWSTD_CONST_CAST (_TypeT*, __src.get ()); if (__ptr) return shared_ptr<_TypeT>(__src, __ptr); return shared_ptr<_TypeT>(); } #if 0 // NOT IMPLEMENTED YET // 2.2.3.7 - shared_ptr I/O template inline basic_ostream<_CharT, _TypeT>& operator<< (basic_ostream<_CharT, _Traits>&, const shared_ptr<_TypeT>&); #endif // 0/1 // 2.2.3.10 - shared_ptr get_deleter template _Deleter* get_deleter (const shared_ptr<_TypeT> &__ptr) { return __ptr._C_get_deleter (); } // 2.2.4 - class template weak_ptr template class weak_ptr { // declare every specialization a friend and grant // template members access to _C_pbody template friend class weak_ptr; template friend class shared_ptr; typedef _RW::__rw_ptr_base _C_base; _C_base *_C_pbody; _TypeT *_C_ptr; public: typedef _TypeT element_type; // constructors weak_ptr (): _C_pbody (0), _C_ptr (0) { } template weak_ptr (const shared_ptr<_TypeU> &__ptr) : _C_pbody (__ptr._C_pbody), _C_ptr (__ptr._C_ptr) { if (_C_pbody) _C_pbody->_C_inc_ref_weak (); } weak_ptr (const weak_ptr &__rhs) : _C_pbody (__rhs._C_pbody), _C_ptr (__rhs._C_ptr) { if (_C_pbody) _C_pbody->_C_inc_ref_weak (); } template weak_ptr (const weak_ptr<_TypeU> &__rhs) : _C_pbody (__rhs._C_pbody), _C_ptr (__rhs._C_ptr) { if (_C_pbody) _C_pbody->_C_inc_ref_weak (); } // destructor ~weak_ptr () { if (_C_pbody) _C_pbody->_C_unref_weak (); #ifdef _RWSTDDEBUG _C_pbody = (_C_base*)0xdeadbeefL; _C_ptr = (element_type*)0xdeadbeefL; #endif // _RWSTDDEBUG } // assignment weak_ptr& operator= (const weak_ptr &__rhs) { if (_C_pbody) _C_pbody->_C_unref_weak (); if ((_C_pbody = __rhs._C_pbody)) _C_pbody->_C_inc_ref_weak (); _C_ptr = __rhs._C_ptr; return *this; } template weak_ptr& operator= (const weak_ptr<_TypeU> &__rhs) { _C_is_convertible ((_TypeU*)0); if (_C_pbody) _C_pbody->_C_unref_weak (); if ((_C_pbody = __rhs._C_pbody)) _C_pbody->_C_inc_ref_weak (); _C_ptr = __rhs._C_ptr; return *this; } template weak_ptr& operator=(const shared_ptr<_TypeU> &__rhs) { _C_is_convertible ((_TypeU*)0); if (_C_pbody) _C_pbody->_C_unref_weak (); if ((_C_pbody = __rhs._C_pbody)) _C_pbody->_C_inc_ref_weak (); _C_ptr = __rhs._C_ptr; return *this; } // modifiers void swap (weak_ptr &__other) { _C_base* const __body = _C_pbody; element_type* const __ptr = _C_ptr; _C_pbody = __other._C_pbody; _C_ptr = __other._C_ptr; __other._C_pbody = __body; __other._C_ptr = __ptr; } void reset () { if (_C_pbody) { _C_pbody->_C_unref_weak (); _C_pbody = 0; _C_ptr = 0; } } // observers long use_count () const { return _C_pbody ? _C_pbody->_C_get_ref () : 0; } bool expired () const { return 0 == use_count (); } shared_ptr lock () const { return expired () ? shared_ptr() : shared_ptr(*this); } // implements 2.2.4.6 - non-member template operator< template bool operator< (const weak_ptr<_TypeU> __rhs) const { return _C_pbody < __rhs._C_pbody; } private: // helper to check whether one pointer is convertible to another // and to enforce the convertibility requirements static void _C_is_convertible (element_type*) { } }; // 2.2.4.6 - weak_ptr comparison template inline bool operator< (const weak_ptr<_TypeT> &__lhs, const weak_ptr<_TypeU> &__rhs) { return __lhs.operator< (__rhs); } // 2.2.4.7 - weak_ptr specialized algorithms template inline void swap (weak_ptr<_TypeT> &__lhs, weak_ptr<_TypeT> &__rhs) { __lhs.swap (__rhs); } // 2.2.5 - class enable_shared_from_this template class enable_shared_from_this; } // namespace tr1 } // namespace std #endif // _RWSTD_TR1_SMARTPTR_INCLUDED