]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / smart_ptr / detail / sp_counted_base_std_atomic.hpp
CommitLineData
7c673cae
FG
1#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_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// detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic
11//
12// Copyright (c) 2007, 2013 Peter Dimov
13//
14// Distributed under the Boost Software License, Version 1.0.
15// See accompanying file LICENSE_1_0.txt or copy at
16// http://www.boost.org/LICENSE_1_0.txt
17
92f5a8d4
TL
18#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
19#include <boost/smart_ptr/detail/sp_noexcept.hpp>
20#include <boost/config.hpp>
7c673cae
FG
21#include <atomic>
22#include <cstdint>
23
24namespace boost
25{
26
27namespace detail
28{
29
92f5a8d4 30inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
7c673cae
FG
31{
32 pw->fetch_add( 1, std::memory_order_relaxed );
33}
34
92f5a8d4 35inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
7c673cae
FG
36{
37 return pw->fetch_sub( 1, std::memory_order_acq_rel );
38}
39
92f5a8d4 40inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
7c673cae
FG
41{
42 // long r = *pw;
43 // if( r != 0 ) ++*pw;
44 // return r;
45
46 std::int_least32_t r = pw->load( std::memory_order_relaxed );
47
48 for( ;; )
49 {
50 if( r == 0 )
51 {
52 return r;
53 }
54
55 if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
56 {
57 return r;
58 }
59 }
60}
61
92f5a8d4 62class BOOST_SYMBOL_VISIBLE sp_counted_base
7c673cae
FG
63{
64private:
65
66 sp_counted_base( sp_counted_base const & );
67 sp_counted_base & operator= ( sp_counted_base const & );
68
11fdf7f2
TL
69 std::atomic_int_least32_t use_count_; // #shared
70 std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
7c673cae
FG
71
72public:
73
92f5a8d4 74 sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
7c673cae
FG
75 {
76 }
77
92f5a8d4 78 virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
7c673cae
FG
79 {
80 }
81
82 // dispose() is called when use_count_ drops to zero, to release
83 // the resources managed by *this.
84
92f5a8d4 85 virtual void dispose() BOOST_SP_NOEXCEPT = 0;
7c673cae
FG
86
87 // destroy() is called when weak_count_ drops to zero.
88
92f5a8d4 89 virtual void destroy() BOOST_SP_NOEXCEPT
7c673cae
FG
90 {
91 delete this;
92 }
93
92f5a8d4
TL
94 virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
95 virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
96 virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
7c673cae 97
92f5a8d4 98 void add_ref_copy() BOOST_SP_NOEXCEPT
7c673cae
FG
99 {
100 atomic_increment( &use_count_ );
101 }
102
92f5a8d4 103 bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
7c673cae
FG
104 {
105 return atomic_conditional_increment( &use_count_ ) != 0;
106 }
107
92f5a8d4 108 void release() BOOST_SP_NOEXCEPT
7c673cae
FG
109 {
110 if( atomic_decrement( &use_count_ ) == 1 )
111 {
112 dispose();
113 weak_release();
114 }
115 }
116
92f5a8d4 117 void weak_add_ref() BOOST_SP_NOEXCEPT
7c673cae
FG
118 {
119 atomic_increment( &weak_count_ );
120 }
121
92f5a8d4 122 void weak_release() BOOST_SP_NOEXCEPT
7c673cae
FG
123 {
124 if( atomic_decrement( &weak_count_ ) == 1 )
125 {
126 destroy();
127 }
128 }
129
92f5a8d4 130 long use_count() const BOOST_SP_NOEXCEPT
7c673cae
FG
131 {
132 return use_count_.load( std::memory_order_acquire );
133 }
134};
135
136} // namespace detail
137
138} // namespace boost
139
140#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED