1 
2 //  helper code for dealing with tracking non-boost shared_ptr/weak_ptr
3 
4 // Copyright Frank Mori Hess 2009.
5 // Distributed under the Boost Software License, Version
6 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 // See http://www.boost.org/libs/signals2 for library home page.
10 
11 #ifndef BOOST_SIGNALS2_FOREIGN_PTR_HPP
12 #define BOOST_SIGNALS2_FOREIGN_PTR_HPP
13 
14 #include <algorithm>
15 #include <boost/config.hpp>
16 #include <boost/assert.hpp>
17 #include <boost/scoped_ptr.hpp>
18 #include <boost/smart_ptr/bad_weak_ptr.hpp>
19 #include <boost/utility/swap.hpp>
20 
21 #ifndef BOOST_NO_CXX11_SMART_PTR
22 #include <memory>
23 #endif
24 
25 namespace boost
26 {
27   template<typename T> class shared_ptr;
28   template<typename T> class weak_ptr;
29 
30   namespace signals2
31   {
32     template<typename WeakPtr> struct weak_ptr_traits
33     {};
34     template<typename T> struct weak_ptr_traits<boost::weak_ptr<T> >
35     {
36       typedef boost::shared_ptr<T> shared_type;
37     };
38 #ifndef BOOST_NO_CXX11_SMART_PTR
39     template<typename T> struct weak_ptr_traits<std::weak_ptr<T> >
40     {
41       typedef std::shared_ptr<T> shared_type;
42     };
43 #endif
44 
45     template<typename SharedPtr> struct shared_ptr_traits
46     {};
47 
48     template<typename T> struct shared_ptr_traits<boost::shared_ptr<T> >
49     {
50       typedef boost::weak_ptr<T> weak_type;
51     };
52 #ifndef BOOST_NO_CXX11_SMART_PTR
53     template<typename T> struct shared_ptr_traits<std::shared_ptr<T> >
54     {
55       typedef std::weak_ptr<T> weak_type;
56     };
57 #endif
58 
59     namespace detail
60     {
61       struct foreign_shared_ptr_impl_base
62       {
~foreign_shared_ptr_impl_baseboost::signals2::detail::foreign_shared_ptr_impl_base63         virtual ~foreign_shared_ptr_impl_base() {}
64         virtual foreign_shared_ptr_impl_base * clone() const = 0;
65       };
66 
67       template<typename FSP>
68       class foreign_shared_ptr_impl: public foreign_shared_ptr_impl_base
69       {
70       public:
foreign_shared_ptr_impl(const FSP & p)71         foreign_shared_ptr_impl(const FSP &p): _p(p)
72         {}
clone() const73         virtual foreign_shared_ptr_impl * clone() const
74         {
75           return new foreign_shared_ptr_impl(*this);
76         }
77       private:
78         FSP _p;
79       };
80 
81       class foreign_void_shared_ptr
82       {
83       public:
foreign_void_shared_ptr()84         foreign_void_shared_ptr():
85           _p(0)
86         {}
foreign_void_shared_ptr(const foreign_void_shared_ptr & other)87         foreign_void_shared_ptr(const foreign_void_shared_ptr &other):
88           _p(other._p->clone())
89         {}
90         template<typename FSP>
foreign_void_shared_ptr(const FSP & fsp)91         explicit foreign_void_shared_ptr(const FSP &fsp):
92           _p(new foreign_shared_ptr_impl<FSP>(fsp))
93         {}
~foreign_void_shared_ptr()94         ~foreign_void_shared_ptr()
95         {
96           delete _p;
97         }
operator =(const foreign_void_shared_ptr & other)98         foreign_void_shared_ptr & operator=(const foreign_void_shared_ptr &other)
99         {
100           if(&other == this) return *this;
101           foreign_void_shared_ptr(other).swap(*this);
102           return *this;
103         }
swap(foreign_void_shared_ptr & other)104         void swap(foreign_void_shared_ptr &other)
105         {
106           boost::swap(_p, other._p);
107         }
108       private:
109         foreign_shared_ptr_impl_base *_p;
110       };
111 
112       struct foreign_weak_ptr_impl_base
113       {
~foreign_weak_ptr_impl_baseboost::signals2::detail::foreign_weak_ptr_impl_base114         virtual ~foreign_weak_ptr_impl_base() {}
115         virtual foreign_void_shared_ptr lock() const = 0;
116         virtual bool expired() const = 0;
117         virtual foreign_weak_ptr_impl_base * clone() const = 0;
118       };
119 
120       template<typename FWP>
121       class foreign_weak_ptr_impl: public foreign_weak_ptr_impl_base
122       {
123       public:
foreign_weak_ptr_impl(const FWP & p)124         foreign_weak_ptr_impl(const FWP &p): _p(p)
125         {}
lock() const126         virtual foreign_void_shared_ptr lock() const
127         {
128           return foreign_void_shared_ptr(_p.lock());
129         }
expired() const130         virtual bool expired() const
131         {
132           return _p.expired();
133         }
clone() const134         virtual foreign_weak_ptr_impl * clone() const
135         {
136           return new foreign_weak_ptr_impl(*this);
137         }
138       private:
139         FWP _p;
140       };
141 
142       class foreign_void_weak_ptr
143       {
144       public:
foreign_void_weak_ptr()145         foreign_void_weak_ptr()
146         {}
foreign_void_weak_ptr(const foreign_void_weak_ptr & other)147         foreign_void_weak_ptr(const foreign_void_weak_ptr &other):
148           _p(other._p->clone())
149         {}
150         template<typename FWP>
foreign_void_weak_ptr(const FWP & fwp)151         explicit foreign_void_weak_ptr(const FWP &fwp):
152           _p(new foreign_weak_ptr_impl<FWP>(fwp))
153         {}
operator =(const foreign_void_weak_ptr & other)154         foreign_void_weak_ptr & operator=(const foreign_void_weak_ptr &other)
155         {
156           if(&other == this) return *this;
157           foreign_void_weak_ptr(other).swap(*this);
158           return *this;
159         }
swap(foreign_void_weak_ptr & other)160         void swap(foreign_void_weak_ptr &other)
161         {
162           boost::swap(_p, other._p);
163         }
lock() const164         foreign_void_shared_ptr lock() const
165         {
166           return _p->lock();
167         }
expired() const168         bool expired() const
169         {
170           return _p->expired();
171         }
172       private:
173         boost::scoped_ptr<foreign_weak_ptr_impl_base> _p;
174       };
175     } // namespace detail
176 
177   } // namespace signals2
178 } // namespace boost
179 
180 #endif  // BOOST_SIGNALS2_FOREIGN_PTR_HPP
181