1 #ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
2 #define BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
3 
4 //
5 //  enable_shared_from_raw.hpp
6 //
7 //  Copyright 2002, 2009, 2014 Peter Dimov
8 //  Copyright 2008-2009 Frank Mori Hess
9 //
10 //  Distributed under the Boost Software License, Version 1.0.
11 //  See accompanying file LICENSE_1_0.txt or copy at
12 //  http://www.boost.org/LICENSE_1_0.txt
13 //
14 
15 #include <boost/config.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <boost/weak_ptr.hpp>
18 #include <boost/assert.hpp>
19 #include <boost/detail/workaround.hpp>
20 
21 namespace boost
22 {
23 template<typename T> boost::shared_ptr<T> shared_from_raw(T *);
24 template<typename T> boost::weak_ptr<T> weak_from_raw(T *);
25 
26 namespace detail
27 {
28 template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
29 
30 } // namespace detail
31 
32 class enable_shared_from_raw
33 {
34 protected:
35 
enable_shared_from_raw()36     enable_shared_from_raw()
37     {
38     }
39 
enable_shared_from_raw(enable_shared_from_raw const &)40     enable_shared_from_raw( enable_shared_from_raw const & )
41     {
42     }
43 
operator =(enable_shared_from_raw const &)44     enable_shared_from_raw & operator=( enable_shared_from_raw const & )
45     {
46         return *this;
47     }
48 
~enable_shared_from_raw()49     ~enable_shared_from_raw()
50     {
51         BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
52     }
53 
54 private:
55 
init_if_expired() const56     void init_if_expired() const
57     {
58         if( weak_this_.expired() )
59         {
60             shared_this_.reset( static_cast<void*>(0), detail::esft2_deleter_wrapper() );
61             weak_this_ = shared_this_;
62         }
63     }
64 
init_if_empty() const65     void init_if_empty() const
66     {
67         if( weak_this_._empty() )
68         {
69             shared_this_.reset( static_cast<void*>(0), detail::esft2_deleter_wrapper() );
70             weak_this_ = shared_this_;
71         }
72     }
73 
74 #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
75 public:
76 #else
77 private:
78     template<class Y> friend class shared_ptr;
79     template<typename T> friend boost::shared_ptr<T> shared_from_raw(T *);
80     template<typename T> friend boost::weak_ptr<T> weak_from_raw(T *);
81     template< class X, class Y > friend inline void detail::sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
82 #endif
83 
shared_from_this() const84     shared_ptr<void const volatile> shared_from_this() const
85     {
86         init_if_expired();
87         return shared_ptr<void const volatile>( weak_this_ );
88     }
89 
shared_from_this() const90     shared_ptr<void const volatile> shared_from_this() const volatile
91     {
92         return const_cast< enable_shared_from_raw const * >( this )->shared_from_this();
93     }
94 
weak_from_this() const95     weak_ptr<void const volatile> weak_from_this() const
96     {
97         init_if_empty();
98         return weak_this_;
99     }
100 
weak_from_this() const101     weak_ptr<void const volatile> weak_from_this() const volatile
102     {
103         return const_cast< enable_shared_from_raw const * >( this )->weak_from_this();
104     }
105 
106     // Note: invoked automatically by shared_ptr; do not call
_internal_accept_owner(shared_ptr<X> * ppx,Y *) const107     template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * ) const
108     {
109         BOOST_ASSERT( ppx != 0 );
110 
111         if( weak_this_.expired() )
112         {
113             weak_this_ = *ppx;
114         }
115         else if( shared_this_.use_count() != 0 )
116         {
117             BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
118 
119             detail::esft2_deleter_wrapper * pd = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
120             BOOST_ASSERT( pd != 0 );
121 
122             pd->set_deleter( *ppx );
123 
124             ppx->reset( shared_this_, ppx->get() );
125             shared_this_.reset();
126         }
127     }
128 
129     mutable weak_ptr<void const volatile> weak_this_;
130 
131 private:
132 
133     mutable shared_ptr<void const volatile> shared_this_;
134 };
135 
136 template<typename T>
shared_from_raw(T * p)137 boost::shared_ptr<T> shared_from_raw(T *p)
138 {
139     BOOST_ASSERT(p != 0);
140     return boost::shared_ptr<T>(p->enable_shared_from_raw::shared_from_this(), p);
141 }
142 
143 template<typename T>
weak_from_raw(T * p)144 boost::weak_ptr<T> weak_from_raw(T *p)
145 {
146     BOOST_ASSERT(p != 0);
147     boost::weak_ptr<T> result;
148     result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p);
149     return result;
150 }
151 
152 namespace detail
153 {
sp_enable_shared_from_this(boost::shared_ptr<X> * ppx,Y const * py,boost::enable_shared_from_raw const * pe)154     template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe )
155     {
156         if( pe != 0 )
157         {
158             pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
159         }
160     }
161 } // namepsace detail
162 
163 } // namespace boost
164 
165 #endif  // #ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
166