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