1 //////////////////////////////////////////////////////////////////////////////
3 // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp
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)
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
35 namespace interprocess
{
38 template<class T
, class VoidAllocator
, class Deleter
>
41 template<class T
, class VoidAllocator
, class Deleter
>
45 typedef typename
boost::pointer_to_other
46 <typename
VoidAllocator::pointer
, T
>::type pointer
;
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
;
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
;
73 : m_px(0), m_pi(0) // nothrow
77 shared_count(const shared_count
&other_shared_count
, const Ptr
&p
)
78 : m_px(p
), m_pi(other_shared_count
.m_pi
)
82 shared_count(const Ptr
&p
, const VoidAllocator
&a
, Deleter d
)
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();
106 ~shared_count() // nothrow
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(); }
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(); }
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
133 if( m_pi == 0 || !m_pi->add_ref_lock() ){
134 boost::throw_exception( boost::interprocess::bad_weak_ptr() );
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
151 pointer
&get_pointer()
154 shared_count
& operator= (shared_count
const & r
) // nothrow
157 counted_impl_ptr tmp
= r
.m_pi
;
159 if(tmp
!= 0) tmp
->add_ref_copy();
160 if(m_pi
!= 0) m_pi
->release();
167 shared_count
& operator= (shared_count
<Y
, VoidAllocator
, Deleter
> const & r
) // nothrow
170 counted_impl_ptr tmp
= r
.m_pi
;
172 if(tmp
!= 0) tmp
->add_ref_copy();
173 if(m_pi
!= 0) m_pi
->release();
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
>
216 typedef typename
boost::pointer_to_other
217 <typename
VoidAllocator::pointer
, T
>::type pointer
;
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
;
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
;
237 weak_count(): m_px(0), m_pi(0) // nothrow
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(); }
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(); }
258 weak_count
& operator= (shared_count
<Y
, VoidAllocator
, Deleter
> const & r
) // nothrow
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();
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();
277 void set_pointer(const pointer
&ptr
)
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();
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
318 #include <boost/interprocess/detail/config_end.hpp>
321 #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED