fix doc example typo
[boost.git] / boost / interprocess / smart_ptr / detail / shared_count.hpp
blob39a64da7ecc4225e32f588b40564a11b619d9299
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp
4 //
5 // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003
6 // (C) Copyright Peter Dimov 2004-2005
7 // (C) Copyright Ion Gaztanaga 2006-2008. Distributed under the Boost
8 // Software License, Version 1.0. (See accompanying file
9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 // See http://www.boost.org/libs/interprocess for documentation.
13 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
15 #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
17 // MS compatible compilers support #pragma once
19 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
20 # pragma once
21 #endif
23 #include <boost/interprocess/detail/config_begin.hpp>
24 #include <boost/interprocess/detail/workaround.hpp>
26 #include <boost/checked_delete.hpp>
27 #include <boost/pointer_to_other.hpp>
28 #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
29 #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
30 #include <boost/interprocess/detail/utilities.hpp>
31 #include <boost/detail/no_exceptions_support.hpp>
32 #include <functional> // std::less
34 namespace boost {
35 namespace interprocess {
36 namespace detail{
38 template<class T, class VoidAllocator, class Deleter>
39 class weak_count;
41 template<class T, class VoidAllocator, class Deleter>
42 class shared_count
44 public:
45 typedef typename boost::pointer_to_other
46 <typename VoidAllocator::pointer, T>::type pointer;
48 private:
49 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
50 typedef typename boost::pointer_to_other
51 <typename VoidAllocator::pointer, counted_impl>::type counted_impl_ptr;
52 typedef typename boost::pointer_to_other
53 <typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
54 typedef typename VoidAllocator::template rebind
55 <counted_impl>::other counted_impl_allocator;
56 typedef typename boost::pointer_to_other
57 <typename VoidAllocator::pointer, const Deleter>::type const_deleter_pointer;
58 typedef typename boost::pointer_to_other
59 <typename VoidAllocator::pointer, const VoidAllocator>::type const_allocator_pointer;
61 pointer m_px;
62 counted_impl_ptr m_pi;
64 template <class T2, class VoidAllocator2, class Deleter2>
65 friend class weak_count;
67 template <class T2, class VoidAllocator2, class Deleter2>
68 friend class shared_count;
70 public:
72 shared_count()
73 : m_px(0), m_pi(0) // nothrow
76 template <class Ptr>
77 shared_count(const shared_count &other_shared_count, const Ptr &p)
78 : m_px(p), m_pi(other_shared_count.m_pi)
81 template <class Ptr>
82 shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
83 : m_px(p), m_pi(0)
85 BOOST_TRY{
86 if(p){
87 counted_impl_allocator alloc(a);
88 m_pi = alloc.allocate(1);
89 //Anti-exception deallocator
90 scoped_ptr<counted_impl,
91 scoped_ptr_dealloc_functor<counted_impl_allocator> >
92 deallocator(m_pi, alloc);
93 //It's more correct to use VoidAllocator::construct but
94 //this needs copy constructor and we don't like it
95 new(detail::get_pointer(m_pi))counted_impl(p, a, d);
96 deallocator.release();
99 BOOST_CATCH (...){
100 d(p); // delete p
101 BOOST_RETHROW
103 BOOST_CATCH_END
106 ~shared_count() // nothrow
108 if( m_pi != 0 )
109 m_pi->release();
112 shared_count(shared_count const & r)
113 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
114 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
116 //this is a test
117 template<class Y>
118 explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
119 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
120 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
122 //this is a test
123 template<class Y>
124 explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
125 : m_px(ptr), m_pi(r.m_pi) // nothrow
126 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
129 explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
130 // throws bad_weak_ptr when r.use_count() == 0
131 : m_pi( r.m_pi )
133 if( m_pi == 0 || !m_pi->add_ref_lock() ){
134 boost::throw_exception( boost::interprocess::bad_weak_ptr() );
138 template<class Y>
139 explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
140 // throws bad_weak_ptr when r.use_count() == 0
141 : m_px(r.m_px), m_pi( r.m_pi )
143 if( m_pi == 0 || !m_pi->add_ref_lock() ){
144 throw( boost::interprocess::bad_weak_ptr() );
148 const pointer &get_pointer() const
149 { return m_px; }
151 pointer &get_pointer()
152 { return m_px; }
154 shared_count & operator= (shared_count const & r) // nothrow
156 m_px = r.m_px;
157 counted_impl_ptr tmp = r.m_pi;
158 if( tmp != m_pi ){
159 if(tmp != 0) tmp->add_ref_copy();
160 if(m_pi != 0) m_pi->release();
161 m_pi = tmp;
163 return *this;
166 template<class Y>
167 shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
169 m_px = r.m_px;
170 counted_impl_ptr tmp = r.m_pi;
171 if( tmp != m_pi ){
172 if(tmp != 0) tmp->add_ref_copy();
173 if(m_pi != 0) m_pi->release();
174 m_pi = tmp;
176 return *this;
179 void swap(shared_count & r) // nothrow
180 { detail::do_swap(m_px, r.m_px); detail::do_swap(m_pi, r.m_pi); }
182 long use_count() const // nothrow
183 { return m_pi != 0? m_pi->use_count(): 0; }
185 bool unique() const // nothrow
186 { return use_count() == 1; }
188 const_deleter_pointer get_deleter() const
189 { return m_pi ? m_pi->get_deleter() : 0; }
191 // const_allocator_pointer get_allocator() const
192 // { return m_pi ? m_pi->get_allocator() : 0; }
194 template<class T2, class VoidAllocator2, class Deleter2>
195 bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
196 { return this->m_pi == other.m_pi; }
198 template<class T2, class VoidAllocator2, class Deleter2>
199 bool internal_less (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
200 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
203 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
204 bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
205 { return a.internal_equal(b); }
207 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
208 bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
209 { return a.internal_less(b); }
212 template<class T, class VoidAllocator, class Deleter>
213 class weak_count
215 public:
216 typedef typename boost::pointer_to_other
217 <typename VoidAllocator::pointer, T>::type pointer;
219 private:
220 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
221 typedef typename boost::pointer_to_other
222 <typename VoidAllocator::pointer, counted_impl>::type counted_impl_ptr;
223 typedef typename boost::pointer_to_other
224 <typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
226 pointer m_px;
227 counted_impl_ptr m_pi;
229 template <class T2, class VoidAllocator2, class Deleter2>
230 friend class weak_count;
232 template <class T2, class VoidAllocator2, class Deleter2>
233 friend class shared_count;
235 public:
237 weak_count(): m_px(0), m_pi(0) // nothrow
240 template <class Y>
241 explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
242 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
243 { if(m_pi != 0) m_pi->weak_add_ref(); }
245 weak_count(weak_count const & r)
246 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
247 { if(m_pi != 0) m_pi->weak_add_ref(); }
249 template<class Y>
250 weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
251 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
252 { if(m_pi != 0) m_pi->weak_add_ref(); }
254 ~weak_count() // nothrow
255 { if(m_pi != 0) m_pi->weak_release(); }
257 template<class Y>
258 weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
260 m_px = r.m_px;
261 counted_impl_ptr tmp = r.m_pi;
262 if(tmp != 0) tmp->weak_add_ref();
263 if(m_pi != 0) m_pi->weak_release();
264 m_pi = tmp;
265 return *this;
268 weak_count & operator= (weak_count const & r) // nothrow
270 counted_impl_ptr tmp = r.m_pi;
271 if(tmp != 0) tmp->weak_add_ref();
272 if(m_pi != 0) m_pi->weak_release();
273 m_pi = tmp;
274 return *this;
277 void set_pointer(const pointer &ptr)
278 { m_px = ptr; }
280 template<class Y>
281 weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow
283 counted_impl_ptr tmp = r.m_pi;
284 if(tmp != 0) tmp->weak_add_ref();
285 if(m_pi != 0) m_pi->weak_release();
286 m_pi = tmp;
287 return *this;
290 void swap(weak_count & r) // nothrow
291 { detail::do_swap(m_px, r.m_px); detail::do_swap(m_pi, r.m_pi); }
293 long use_count() const // nothrow
294 { return m_pi != 0? m_pi->use_count() : 0; }
296 template<class T2, class VoidAllocator2, class Deleter2>
297 bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
298 { return this->m_pi == other.m_pi; }
300 template<class T2, class VoidAllocator2, class Deleter2>
301 bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
302 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
305 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
306 bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
307 { return a.internal_equal(b); }
309 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
310 bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
311 { return a.internal_less(b); }
313 } // namespace detail
314 } // namespace interprocess
315 } // namespace boost
318 #include <boost/interprocess/detail/config_end.hpp>
321 #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED