Line data Source code
1 : #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
2 : #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
3 :
4 : // MS compatible compilers support #pragma once
5 :
6 : #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 : # pragma once
8 : #endif
9 :
10 : //
11 : // detail/shared_count.hpp
12 : //
13 : // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14 : // Copyright 2004-2005 Peter Dimov
15 : //
16 : // Distributed under the Boost Software License, Version 1.0. (See
17 : // accompanying file LICENSE_1_0.txt or copy at
18 : // http://www.boost.org/LICENSE_1_0.txt)
19 : //
20 :
21 : #include <boost/smart_ptr/bad_weak_ptr.hpp>
22 : #include <boost/smart_ptr/detail/sp_counted_base.hpp>
23 : #include <boost/smart_ptr/detail/sp_counted_impl.hpp>
24 : #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
25 : #include <boost/smart_ptr/detail/deprecated_macros.hpp>
26 : #include <boost/core/checked_delete.hpp>
27 : #include <boost/throw_exception.hpp>
28 : #include <boost/core/addressof.hpp>
29 : #include <boost/config.hpp>
30 : #include <boost/config/workaround.hpp>
31 : #include <cstdint>
32 : #include <memory> // std::auto_ptr
33 : #include <functional> // std::less
34 : #include <cstddef> // std::size_t
35 :
36 : #ifdef BOOST_NO_EXCEPTIONS
37 : # include <new> // std::bad_alloc
38 : #endif
39 :
40 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
41 : #pragma GCC diagnostic push
42 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
43 : #endif
44 :
45 : namespace boost
46 : {
47 :
48 : namespace movelib
49 : {
50 :
51 : template< class T, class D > class unique_ptr;
52 :
53 : } // namespace movelib
54 :
55 : namespace detail
56 : {
57 :
58 : struct sp_nothrow_tag {};
59 :
60 : template< class D > struct sp_inplace_tag
61 : {
62 : };
63 :
64 : template< class T > class sp_reference_wrapper
65 : {
66 : public:
67 :
68 : explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
69 : {
70 : }
71 :
72 : template< class Y > void operator()( Y * p ) const
73 : {
74 : (*t_)( p );
75 : }
76 :
77 : private:
78 :
79 : T * t_;
80 : };
81 :
82 : template< class D > struct sp_convert_reference
83 : {
84 : typedef D type;
85 : };
86 :
87 : template< class D > struct sp_convert_reference< D& >
88 : {
89 : typedef sp_reference_wrapper< D > type;
90 : };
91 :
92 : template<class T> std::size_t sp_hash_pointer( T* p ) noexcept
93 : {
94 : std::uintptr_t v = reinterpret_cast<std::uintptr_t>( p );
95 :
96 : // match boost::hash<T*>
97 : return static_cast<std::size_t>( v + ( v >> 3 ) );
98 : }
99 :
100 : class weak_count;
101 :
102 : class shared_count
103 : {
104 : private:
105 :
106 : sp_counted_base * pi_;
107 :
108 : friend class weak_count;
109 :
110 : public:
111 :
112 20905826 : constexpr shared_count() noexcept: pi_(0)
113 10452913 : {
114 20905826 : }
115 :
116 : constexpr explicit shared_count( sp_counted_base * pi ) noexcept: pi_( pi )
117 : {
118 : }
119 :
120 962526 : template<class Y> explicit shared_count( Y * p ): pi_( 0 )
121 481263 : {
122 : #ifndef BOOST_NO_EXCEPTIONS
123 :
124 : try
125 : {
126 481263 : pi_ = new sp_counted_impl_p<Y>( p );
127 481263 : }
128 : catch(...)
129 : {
130 0 : boost::checked_delete( p );
131 0 : throw;
132 0 : }
133 :
134 : #else
135 :
136 : pi_ = new sp_counted_impl_p<Y>( p );
137 :
138 : if( pi_ == 0 )
139 : {
140 : boost::checked_delete( p );
141 : boost::throw_exception( std::bad_alloc() );
142 : }
143 :
144 : #endif
145 962526 : }
146 :
147 : template<class P, class D> shared_count( P p, D d ): pi_(0)
148 : {
149 : #ifndef BOOST_NO_EXCEPTIONS
150 :
151 : try
152 : {
153 : pi_ = new sp_counted_impl_pd<P, D>(p, d);
154 : }
155 : catch(...)
156 : {
157 : d(p); // delete p
158 : throw;
159 : }
160 :
161 : #else
162 :
163 : pi_ = new sp_counted_impl_pd<P, D>(p, d);
164 :
165 : if(pi_ == 0)
166 : {
167 : d(p); // delete p
168 : boost::throw_exception(std::bad_alloc());
169 : }
170 :
171 : #endif
172 : }
173 :
174 239088 : template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
175 119544 : {
176 : #ifndef BOOST_NO_EXCEPTIONS
177 :
178 : try
179 : {
180 119544 : pi_ = new sp_counted_impl_pd< P, D >( p );
181 119544 : }
182 : catch( ... )
183 : {
184 0 : D::operator_fn( p ); // delete p
185 0 : throw;
186 0 : }
187 :
188 : #else
189 :
190 : pi_ = new sp_counted_impl_pd< P, D >( p );
191 :
192 : if( pi_ == 0 )
193 : {
194 : D::operator_fn( p ); // delete p
195 : boost::throw_exception( std::bad_alloc() );
196 : }
197 :
198 : #endif // #ifndef BOOST_NO_EXCEPTIONS
199 239088 : }
200 :
201 : template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
202 : {
203 : typedef sp_counted_impl_pda<P, D, A> impl_type;
204 :
205 : typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
206 :
207 : A2 a2( a );
208 :
209 : #ifndef BOOST_NO_EXCEPTIONS
210 :
211 : try
212 : {
213 : pi_ = a2.allocate( 1 );
214 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
215 : }
216 : catch(...)
217 : {
218 : d( p );
219 :
220 : if( pi_ != 0 )
221 : {
222 : a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
223 : }
224 :
225 : throw;
226 : }
227 :
228 : #else
229 :
230 : pi_ = a2.allocate( 1 );
231 :
232 : if( pi_ != 0 )
233 : {
234 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
235 : }
236 : else
237 : {
238 : d( p );
239 : boost::throw_exception( std::bad_alloc() );
240 : }
241 :
242 : #endif
243 : }
244 :
245 : template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
246 : {
247 : typedef sp_counted_impl_pda< P, D, A > impl_type;
248 :
249 : typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
250 :
251 : A2 a2( a );
252 :
253 : #ifndef BOOST_NO_EXCEPTIONS
254 :
255 : try
256 : {
257 : pi_ = a2.allocate( 1 );
258 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
259 : }
260 : catch(...)
261 : {
262 : D::operator_fn( p );
263 :
264 : if( pi_ != 0 )
265 : {
266 : a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
267 : }
268 :
269 : throw;
270 : }
271 :
272 : #else
273 :
274 : pi_ = a2.allocate( 1 );
275 :
276 : if( pi_ != 0 )
277 : {
278 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
279 : }
280 : else
281 : {
282 : D::operator_fn( p );
283 : boost::throw_exception( std::bad_alloc() );
284 : }
285 :
286 : #endif // #ifndef BOOST_NO_EXCEPTIONS
287 : }
288 :
289 : #ifndef BOOST_NO_AUTO_PTR
290 :
291 : // auto_ptr<Y> is special cased to provide the strong guarantee
292 :
293 : template<class Y>
294 : explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
295 : {
296 : #ifdef BOOST_NO_EXCEPTIONS
297 :
298 : if( pi_ == 0 )
299 : {
300 : boost::throw_exception(std::bad_alloc());
301 : }
302 :
303 : #endif
304 :
305 : r.release();
306 : }
307 :
308 : #endif
309 :
310 : template<class Y, class D>
311 : explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
312 : {
313 : typedef typename sp_convert_reference<D>::type D2;
314 :
315 : D2 d2( static_cast<D&&>( r.get_deleter() ) );
316 : pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
317 :
318 : #ifdef BOOST_NO_EXCEPTIONS
319 :
320 : if( pi_ == 0 )
321 : {
322 : boost::throw_exception( std::bad_alloc() );
323 : }
324 :
325 : #endif
326 :
327 : r.release();
328 : }
329 :
330 : template<class Y, class D>
331 : explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
332 : {
333 : typedef typename sp_convert_reference<D>::type D2;
334 :
335 : D2 d2( r.get_deleter() );
336 : pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
337 :
338 : #ifdef BOOST_NO_EXCEPTIONS
339 :
340 : if( pi_ == 0 )
341 : {
342 : boost::throw_exception( std::bad_alloc() );
343 : }
344 :
345 : #endif
346 :
347 : r.release();
348 : }
349 :
350 25943674 : ~shared_count() /*noexcept*/
351 12971837 : {
352 12971837 : if( pi_ != 0 ) pi_->release();
353 25943674 : }
354 :
355 3385170 : shared_count(shared_count const & r) noexcept: pi_(r.pi_)
356 1692585 : {
357 1692585 : if( pi_ != 0 ) pi_->add_ref_copy();
358 3385170 : }
359 :
360 764006 : shared_count(shared_count && r) noexcept: pi_(r.pi_)
361 382003 : {
362 382003 : r.pi_ = 0;
363 764006 : }
364 :
365 : explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
366 : shared_count( weak_count const & r, sp_nothrow_tag ) noexcept; // constructs an empty *this when r.use_count() == 0
367 :
368 : shared_count & operator= (shared_count const & r) noexcept
369 : {
370 : sp_counted_base * tmp = r.pi_;
371 :
372 : if( tmp != pi_ )
373 : {
374 : if( tmp != 0 ) tmp->add_ref_copy();
375 : if( pi_ != 0 ) pi_->release();
376 : pi_ = tmp;
377 : }
378 :
379 : return *this;
380 : }
381 :
382 1739127 : void swap(shared_count & r) noexcept
383 : {
384 1739127 : sp_counted_base * tmp = r.pi_;
385 1739127 : r.pi_ = pi_;
386 1739127 : pi_ = tmp;
387 1739127 : }
388 :
389 3224272 : long use_count() const noexcept
390 : {
391 3224272 : return pi_ != 0? pi_->use_count(): 0;
392 : }
393 :
394 3224272 : bool unique() const noexcept
395 : {
396 3224272 : return use_count() == 1;
397 : }
398 :
399 215391 : bool empty() const noexcept
400 : {
401 215391 : return pi_ == 0;
402 : }
403 :
404 : bool operator==( shared_count const & r ) const noexcept
405 : {
406 : return pi_ == r.pi_;
407 : }
408 :
409 : bool operator==( weak_count const & r ) const noexcept;
410 :
411 : bool operator<( shared_count const & r ) const noexcept
412 : {
413 : return std::less<sp_counted_base *>()( pi_, r.pi_ );
414 : }
415 :
416 : bool operator<( weak_count const & r ) const noexcept;
417 :
418 : void * get_deleter( sp_typeinfo_ const & ti ) const noexcept
419 : {
420 : return pi_? pi_->get_deleter( ti ): 0;
421 : }
422 :
423 : void * get_local_deleter( sp_typeinfo_ const & ti ) const noexcept
424 : {
425 : return pi_? pi_->get_local_deleter( ti ): 0;
426 : }
427 :
428 119544 : void * get_untyped_deleter() const noexcept
429 : {
430 119544 : return pi_? pi_->get_untyped_deleter(): 0;
431 : }
432 :
433 : std::size_t hash_value() const noexcept
434 : {
435 : return sp_hash_pointer( pi_ );
436 : }
437 : };
438 :
439 :
440 : class weak_count
441 : {
442 : private:
443 :
444 : sp_counted_base * pi_;
445 :
446 : friend class shared_count;
447 :
448 : public:
449 :
450 119848 : constexpr weak_count() noexcept: pi_(0)
451 59924 : {
452 119848 : }
453 :
454 86066 : weak_count(shared_count const & r) noexcept: pi_(r.pi_)
455 43033 : {
456 43033 : if(pi_ != 0) pi_->weak_add_ref();
457 86066 : }
458 :
459 99322 : weak_count(weak_count const & r) noexcept: pi_(r.pi_)
460 49661 : {
461 49661 : if(pi_ != 0) pi_->weak_add_ref();
462 99322 : }
463 :
464 : // Move support
465 :
466 160728 : weak_count(weak_count && r) noexcept: pi_(r.pi_)
467 80364 : {
468 80364 : r.pi_ = 0;
469 160728 : }
470 :
471 395334 : ~weak_count() /*noexcept*/
472 197667 : {
473 197667 : if(pi_ != 0) pi_->weak_release();
474 395334 : }
475 :
476 : weak_count & operator= (shared_count const & r) noexcept
477 : {
478 : sp_counted_base * tmp = r.pi_;
479 :
480 : if( tmp != pi_ )
481 : {
482 : if(tmp != 0) tmp->weak_add_ref();
483 : if(pi_ != 0) pi_->weak_release();
484 : pi_ = tmp;
485 : }
486 :
487 : return *this;
488 : }
489 :
490 : weak_count & operator= (weak_count const & r) noexcept
491 : {
492 : sp_counted_base * tmp = r.pi_;
493 :
494 : if( tmp != pi_ )
495 : {
496 : if(tmp != 0) tmp->weak_add_ref();
497 : if(pi_ != 0) pi_->weak_release();
498 : pi_ = tmp;
499 : }
500 :
501 : return *this;
502 : }
503 :
504 28168 : void swap(weak_count & r) noexcept
505 : {
506 28168 : sp_counted_base * tmp = r.pi_;
507 28168 : r.pi_ = pi_;
508 28168 : pi_ = tmp;
509 28168 : }
510 :
511 481295 : long use_count() const noexcept
512 : {
513 481295 : return pi_ != 0? pi_->use_count(): 0;
514 : }
515 :
516 : bool empty() const noexcept
517 : {
518 : return pi_ == 0;
519 : }
520 :
521 : bool operator==( weak_count const & r ) const noexcept
522 : {
523 : return pi_ == r.pi_;
524 : }
525 :
526 : bool operator==( shared_count const & r ) const noexcept
527 : {
528 : return pi_ == r.pi_;
529 : }
530 :
531 : bool operator<( weak_count const & r ) const noexcept
532 : {
533 : return std::less<sp_counted_base *>()( pi_, r.pi_ );
534 : }
535 :
536 : bool operator<( shared_count const & r ) const noexcept
537 : {
538 : return std::less<sp_counted_base *>()( pi_, r.pi_ );
539 : }
540 :
541 : std::size_t hash_value() const noexcept
542 : {
543 : return sp_hash_pointer( pi_ );
544 : }
545 : };
546 :
547 : inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
548 : {
549 : if( pi_ == 0 || !pi_->add_ref_lock() )
550 : {
551 : boost::throw_exception( boost::bad_weak_ptr() );
552 : }
553 : }
554 :
555 430784 : inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) noexcept: pi_( r.pi_ )
556 215392 : {
557 215392 : if( pi_ != 0 && !pi_->add_ref_lock() )
558 : {
559 0 : pi_ = 0;
560 0 : }
561 430784 : }
562 :
563 : inline bool shared_count::operator==( weak_count const & r ) const noexcept
564 : {
565 : return pi_ == r.pi_;
566 : }
567 :
568 : inline bool shared_count::operator<( weak_count const & r ) const noexcept
569 : {
570 : return std::less<sp_counted_base *>()( pi_, r.pi_ );
571 : }
572 :
573 : } // namespace detail
574 :
575 : } // namespace boost
576 :
577 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
578 : #pragma GCC diagnostic pop
579 : #endif
580 :
581 : #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|