612 lines
14 KiB
C++
612 lines
14 KiB
C++
// -*- 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 <rw/_autoptr.h>
|
|
#include <rw/_exception.h>
|
|
#include <rw/_mutex.h>
|
|
#include <rw/_defs.h>
|
|
|
|
|
|
_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 <class _TypeU>
|
|
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 <class _TypeU, class _Deleter>
|
|
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 _TypeT>
|
|
class weak_ptr;
|
|
|
|
|
|
// 2.2.3 - class template shared_ptr
|
|
template <class _TypeT>
|
|
class shared_ptr
|
|
{
|
|
// declare every specialization a friend and grant
|
|
// template members access to _C_ptr
|
|
template <class _TypeU>
|
|
friend class shared_ptr;
|
|
|
|
template <class _TypeU>
|
|
friend class weak_ptr;
|
|
|
|
template <class _TypeU, class _TypeV>
|
|
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 <class _TypeU>
|
|
_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 <class _TypeU>
|
|
_EXPLICIT
|
|
shared_ptr (_TypeU *__ptr)
|
|
: _C_pbody (__ptr ? new _RW::__rw_ptr_body<_TypeU>(__ptr) : 0),
|
|
_C_ptr (__ptr) { /* empty */ }
|
|
|
|
template <class _TypeU, class _Deleter>
|
|
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 <class _TypeU>
|
|
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 <class _TypeU>
|
|
_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 <class _TypeU>
|
|
_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 <class _TypeU>
|
|
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 <class _TypeU>
|
|
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 <class _TypeU>
|
|
void reset (_TypeU *__ptr) {
|
|
shared_ptr<_TypeU>(__ptr).swap (*this);
|
|
}
|
|
|
|
template <class _TypeU, class _Deleter>
|
|
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<element_type>::_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 <class _Deleter>
|
|
_Deleter* _C_get_deleter () const {
|
|
return _RWSTD_STATIC_CAST (_Deleter*,
|
|
_C_pbody ? _C_pbody->_C_get_deleter () : 0);
|
|
}
|
|
|
|
template <class _TypeU>
|
|
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 <class _TypeT, class _TypeU>
|
|
inline bool
|
|
operator== (const shared_ptr<_TypeT> &__lhs, const shared_ptr<_TypeU> &__rhs)
|
|
{
|
|
return __lhs.get () == __rhs.get ();
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline bool
|
|
operator!= (const shared_ptr<_TypeT> &__lhs, const shared_ptr<_TypeU> &__rhs)
|
|
{
|
|
return __lhs.get () != __rhs.get ();
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
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 <class _TypeT>
|
|
inline void
|
|
swap (shared_ptr<_TypeT> &__lhs, shared_ptr<_TypeT> &__rhs)
|
|
{
|
|
__lhs.swap (__rhs);
|
|
}
|
|
|
|
|
|
// 2.2.3.9 - shared_ptr casts
|
|
template <class _TypeT, class _TypeU>
|
|
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 <class _TypeT, class _TypeU>
|
|
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 <class _TypeT, class _TypeU>
|
|
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 <class _CharT, class _Traits, class _TypeT>
|
|
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 <class _Deleter, class _TypeT>
|
|
_Deleter*
|
|
get_deleter (const shared_ptr<_TypeT> &__ptr)
|
|
{
|
|
return __ptr._C_get_deleter ();
|
|
}
|
|
|
|
|
|
// 2.2.4 - class template weak_ptr
|
|
template <class _TypeT>
|
|
class weak_ptr
|
|
{
|
|
// declare every specialization a friend and grant
|
|
// template members access to _C_pbody
|
|
template <class _TypeU>
|
|
friend class weak_ptr;
|
|
|
|
template <class _TypeU>
|
|
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 <class _TypeU>
|
|
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 <class _TypeU>
|
|
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 <class _TypeU>
|
|
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<class _TypeU>
|
|
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<element_type>
|
|
lock () const {
|
|
return expired () ? shared_ptr<element_type>()
|
|
: shared_ptr<element_type>(*this);
|
|
}
|
|
|
|
// implements 2.2.4.6 - non-member template operator<
|
|
template <class _TypeU>
|
|
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 <class _TypeT, class _TypeU>
|
|
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 <class _TypeT>
|
|
inline void
|
|
swap (weak_ptr<_TypeT> &__lhs, weak_ptr<_TypeT> &__rhs)
|
|
{
|
|
__lhs.swap (__rhs);
|
|
}
|
|
|
|
|
|
// 2.2.5 - class enable_shared_from_this
|
|
template <class _TypeT>
|
|
class enable_shared_from_this;
|
|
|
|
|
|
} // namespace tr1
|
|
|
|
} // namespace std
|
|
|
|
|
|
#endif // _RWSTD_TR1_SMARTPTR_INCLUDED
|