• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2012. 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)
10 //
11 // See http://www.boost.org/libs/interprocess for documentation.
12 //
13 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
15 #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
16 
17 #ifndef BOOST_CONFIG_HPP
18 #  include <boost/config.hpp>
19 #endif
20 #
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 # pragma once
23 #endif
24 
25 #include <boost/interprocess/detail/config_begin.hpp>
26 #include <boost/interprocess/detail/workaround.hpp>
27 
28 #include <boost/checked_delete.hpp>
29 #include <boost/intrusive/pointer_traits.hpp>
30 #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
31 #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
32 #include <boost/interprocess/detail/utilities.hpp>
33 #include <boost/container/allocator_traits.hpp>
34 #include <boost/core/no_exceptions_support.hpp>
35 #include <boost/move/adl_move_swap.hpp>
36 #include <boost/intrusive/detail/minimal_less_equal_header.hpp>   //std::less
37 #include <boost/container/detail/placement_new.hpp>
38 
39 namespace boost {
40 namespace interprocess {
41 namespace ipcdetail{
42 
43 template<class T, class VoidAllocator, class Deleter>
44 class weak_count;
45 
46 template<class T, class VoidAllocator, class Deleter>
47 class shared_count
48 {
49    public:
50    typedef typename boost::intrusive::
51       pointer_traits<typename VoidAllocator::pointer>::template
52          rebind_pointer<T>::type                         pointer;
53 
54    private:
55    typedef sp_counted_impl_pd<VoidAllocator, Deleter>       counted_impl;
56 
57    typedef typename boost::intrusive::
58       pointer_traits<typename VoidAllocator::pointer>::template
59          rebind_pointer<counted_impl>::type                         counted_impl_ptr;
60    typedef typename boost::intrusive::
61       pointer_traits<typename VoidAllocator::pointer>::template
62          rebind_pointer<sp_counted_base>::type                       counted_base_ptr;
63 
64    typedef boost::container::allocator_traits<VoidAllocator>         vallocator_traits;
65 
66    typedef typename vallocator_traits::template
67       portable_rebind_alloc<counted_impl>::type                      counted_impl_allocator;
68 
69    typedef typename boost::intrusive::
70       pointer_traits<typename VoidAllocator::pointer>::template
71          rebind_pointer<const Deleter>::type                         const_deleter_pointer;
72 
73    typedef typename boost::intrusive::
74       pointer_traits<typename VoidAllocator::pointer>::template
75          rebind_pointer<const VoidAllocator>::type                   const_allocator_pointer;
76 
77    pointer           m_px;
78    counted_impl_ptr  m_pi;
79 
80    template <class T2, class VoidAllocator2, class Deleter2>
81    friend class weak_count;
82 
83    template <class T2, class VoidAllocator2, class Deleter2>
84    friend class shared_count;
85 
86    public:
87 
shared_count()88    shared_count()
89       :  m_px(0), m_pi(0) // nothrow
90    {}
91 
92    template <class Ptr>
shared_count(const shared_count & other_shared_count,const Ptr & p)93    shared_count(const shared_count &other_shared_count, const Ptr &p)
94       :  m_px(p), m_pi(other_shared_count.m_pi)
95    {}
96 
97    template <class Ptr>
shared_count(const Ptr & p,const VoidAllocator & a,Deleter d)98    shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
99       :  m_px(p), m_pi(0)
100    {
101       BOOST_TRY{
102          if(p){
103             counted_impl_allocator alloc(a);
104             m_pi = alloc.allocate(1);
105             //Anti-exception deallocator
106             scoped_ptr<counted_impl,
107                      scoped_ptr_dealloc_functor<counted_impl_allocator> >
108                         deallocator(m_pi, alloc);
109             //It's more correct to use VoidAllocator::construct but
110             //this needs copy constructor and we don't like it
111             ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d);
112             deallocator.release();
113          }
114       }
115       BOOST_CATCH (...){
116          d(p); // delete p
117          BOOST_RETHROW
118       }
119       BOOST_CATCH_END
120    }
121 
~shared_count()122    ~shared_count() // nothrow
123    {
124       if(m_pi)
125          m_pi->release();
126    }
127 
shared_count(shared_count const & r)128    shared_count(shared_count const & r)
129       :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
130    { if( m_pi != 0 ) m_pi->add_ref_copy(); }
131 
132    //this is a test
133    template<class Y>
shared_count(shared_count<Y,VoidAllocator,Deleter> const & r)134    explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
135       :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
136    {  if( m_pi != 0 ) m_pi->add_ref_copy();  }
137 
138    //this is a test
139    template<class Y>
shared_count(const pointer & ptr,shared_count<Y,VoidAllocator,Deleter> const & r)140    explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
141       :  m_px(ptr), m_pi(r.m_pi) // nothrow
142    {  if( m_pi != 0 ) m_pi->add_ref_copy();  }
143 
144 /*
145    explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
146       // throws bad_weak_ptr when r.use_count() == 0
147       : m_pi( r.m_pi )
148    {
149       if( m_pi == 0 || !m_pi->add_ref_lock() ){
150          boost::throw_exception( boost::interprocess::bad_weak_ptr() );
151       }
152    }
153 */
154    template<class Y>
shared_count(weak_count<Y,VoidAllocator,Deleter> const & r)155    explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
156       // throws bad_weak_ptr when r.use_count() == 0
157       : m_px(r.m_px), m_pi( r.m_pi )
158    {
159       if( m_pi == 0 || !m_pi->add_ref_lock() ){
160          throw( boost::interprocess::bad_weak_ptr() );
161       }
162    }
163 
to_raw_pointer() const164    const pointer &to_raw_pointer() const
165    {  return m_px;   }
166 
to_raw_pointer()167    pointer &to_raw_pointer()
168    {  return m_px;   }
169 
operator =(shared_count const & r)170    shared_count & operator= (shared_count const & r) // nothrow
171    {
172       m_px = r.m_px;
173       counted_impl_ptr tmp = r.m_pi;
174       if( tmp != m_pi ){
175          if(tmp != 0)   tmp->add_ref_copy();
176          if(m_pi != 0)  m_pi->release();
177          m_pi = tmp;
178       }
179       return *this;
180    }
181 
182    template<class Y>
operator =(shared_count<Y,VoidAllocator,Deleter> const & r)183    shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
184    {
185       m_px = r.m_px;
186       counted_impl_ptr tmp = r.m_pi;
187       if( tmp != m_pi ){
188          if(tmp != 0)   tmp->add_ref_copy();
189          if(m_pi != 0)  m_pi->release();
190          m_pi = tmp;
191       }
192       return *this;
193    }
194 
swap(shared_count & r)195    void swap(shared_count & r) // nothrow
196    {  ::boost::adl_move_swap(m_px, r.m_px);  ::boost::adl_move_swap(m_pi, r.m_pi);   }
197 
use_count() const198    long use_count() const // nothrow
199    {  return m_pi != 0? m_pi->use_count(): 0;  }
200 
unique() const201    bool unique() const // nothrow
202    {  return use_count() == 1;   }
203 
get_deleter() const204    const_deleter_pointer get_deleter() const
205    {  return m_pi ? m_pi->get_deleter() : 0; }
206 
207 //   const_allocator_pointer get_allocator() const
208 //   {  return m_pi ? m_pi->get_allocator() : 0; }
209 
210    template<class T2, class VoidAllocator2, class Deleter2>
internal_equal(shared_count<T2,VoidAllocator2,Deleter2> const & other) const211    bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
212    {  return this->m_pi == other.m_pi;   }
213 
214    template<class T2, class VoidAllocator2, class Deleter2>
internal_less(shared_count<T2,VoidAllocator2,Deleter2> const & other) const215    bool internal_less  (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
216    {  return std::less<counted_base_ptr>()(this->m_pi, other.m_pi);  }
217 };
218 
219 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
operator ==(shared_count<T,VoidAllocator,Deleter> const & a,shared_count<T2,VoidAllocator2,Deleter2> const & b)220 bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
221 {  return a.internal_equal(b);  }
222 
223 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
operator <(shared_count<T,VoidAllocator,Deleter> const & a,shared_count<T2,VoidAllocator2,Deleter2> const & b)224 bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
225 {  return a.internal_less(b);   }
226 
227 
228 template<class T, class VoidAllocator, class Deleter>
229 class weak_count
230 {
231    public:
232    typedef typename boost::intrusive::
233       pointer_traits<typename VoidAllocator::pointer>::template
234          rebind_pointer<T>::type                         pointer;
235 
236    private:
237 
238    typedef sp_counted_impl_pd<VoidAllocator, Deleter>                counted_impl;
239 
240    typedef typename boost::intrusive::
241       pointer_traits<typename VoidAllocator::pointer>::template
242          rebind_pointer<counted_impl>::type                          counted_impl_ptr;
243    typedef typename boost::intrusive::
244       pointer_traits<typename VoidAllocator::pointer>::template
245          rebind_pointer<sp_counted_base>::type                       counted_base_ptr;
246 
247    pointer           m_px;
248    counted_impl_ptr  m_pi;
249 
250    template <class T2, class VoidAllocator2, class Deleter2>
251    friend class weak_count;
252 
253    template <class T2, class VoidAllocator2, class Deleter2>
254    friend class shared_count;
255 
256    public:
257 
weak_count()258    weak_count(): m_px(0), m_pi(0) // nothrow
259    {}
260 
261    template <class Y>
weak_count(shared_count<Y,VoidAllocator,Deleter> const & r)262    explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
263       :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
264    {  if(m_pi != 0) m_pi->weak_add_ref(); }
265 
weak_count(weak_count const & r)266    weak_count(weak_count const & r)
267       :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
268    {  if(m_pi != 0) m_pi->weak_add_ref(); }
269 
270    template<class Y>
weak_count(weak_count<Y,VoidAllocator,Deleter> const & r)271    weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
272       : m_px(r.m_px), m_pi(r.m_pi) // nothrow
273    {  if(m_pi != 0) m_pi->weak_add_ref(); }
274 
~weak_count()275    ~weak_count() // nothrow
276    {  if(m_pi != 0) m_pi->weak_release(); }
277 
278    template<class Y>
operator =(shared_count<Y,VoidAllocator,Deleter> const & r)279    weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
280    {
281       m_px = r.m_px;
282       counted_impl_ptr tmp = r.m_pi;
283       if(tmp != 0)   tmp->weak_add_ref();
284       if(m_pi != 0)  m_pi->weak_release();
285       m_pi = tmp;
286       return *this;
287    }
288 
operator =(weak_count const & r)289    weak_count & operator= (weak_count const & r) // nothrow
290    {
291       m_px = r.m_px;
292       counted_impl_ptr tmp = r.m_pi;
293       if(tmp != 0) tmp->weak_add_ref();
294       if(m_pi != 0) m_pi->weak_release();
295       m_pi = tmp;
296       return *this;
297    }
298 
set_pointer(const pointer & ptr)299    void set_pointer(const pointer &ptr)
300    {  m_px = ptr; }
301 
302    template<class Y>
operator =(weak_count<Y,VoidAllocator,Deleter> const & r)303    weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow
304    {
305       counted_impl_ptr tmp = r.m_pi;
306       if(tmp != 0) tmp->weak_add_ref();
307       if(m_pi != 0) m_pi->weak_release();
308       m_pi = tmp;
309       return *this;
310    }
311 
swap(weak_count & r)312    void swap(weak_count & r) // nothrow
313    {  ::boost::adl_move_swap(m_px, r.m_px);  ::boost::adl_move_swap(m_pi, r.m_pi);   }
314 
use_count() const315    long use_count() const // nothrow
316    {  return m_pi != 0? m_pi->use_count() : 0;   }
317 
318    template<class T2, class VoidAllocator2, class Deleter2>
internal_equal(weak_count<T2,VoidAllocator2,Deleter2> const & other) const319    bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
320    {  return this->m_pi == other.m_pi;   }
321 
322    template<class T2, class VoidAllocator2, class Deleter2>
internal_less(weak_count<T2,VoidAllocator2,Deleter2> const & other) const323    bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
324    {  return std::less<counted_base_ptr>()(this->m_pi, other.m_pi);  }
325 };
326 
327 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
operator ==(weak_count<T,VoidAllocator,Deleter> const & a,weak_count<T2,VoidAllocator2,Deleter2> const & b)328 bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
329 {  return a.internal_equal(b);  }
330 
331 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
operator <(weak_count<T,VoidAllocator,Deleter> const & a,weak_count<T2,VoidAllocator2,Deleter2> const & b)332 bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
333 {  return a.internal_less(b);   }
334 
335 } // namespace ipcdetail
336 } // namespace interprocess
337 } // namespace boost
338 
339 
340 #include <boost/interprocess/detail/config_end.hpp>
341 
342 
343 #endif  // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
344