1#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_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_clang.hpp - __c11 clang intrinsics
11//
12// Copyright (c) 2007, 2013, 2015 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
18#include <boost/detail/sp_typeinfo.hpp>
19#include <boost/cstdint.hpp>
20
21namespace boost
22{
23
24namespace detail
25{
26
27typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
28
29inline void atomic_increment( atomic_int_least32_t * pw )
30{
31 __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
32}
33
34inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
35{
36 return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
37}
38
39inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
40{
41 // long r = *pw;
42 // if( r != 0 ) ++*pw;
43 // return r;
44
45 boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
46
47 for( ;; )
48 {
49 if( r == 0 )
50 {
51 return r;
52 }
53
54 if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
55 {
56 return r;
57 }
58 }
59}
60
61#if defined(__clang__)
62# pragma clang diagnostic push
63# pragma clang diagnostic ignored "-Wweak-vtables"
64#endif
65
66class sp_counted_base
67{
68private:
69
70 sp_counted_base( sp_counted_base const & );
71 sp_counted_base & operator= ( sp_counted_base const & );
72
73 atomic_int_least32_t use_count_; // #shared
74 atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
75
76public:
77
78 sp_counted_base()
79 {
80 __c11_atomic_init( &use_count_, 1 );
81 __c11_atomic_init( &weak_count_, 1 );
82 }
83
84 virtual ~sp_counted_base() // nothrow
85 {
86 }
87
88 // dispose() is called when use_count_ drops to zero, to release
89 // the resources managed by *this.
90
91 virtual void dispose() = 0; // nothrow
92
93 // destroy() is called when weak_count_ drops to zero.
94
95 virtual void destroy() // nothrow
96 {
97 delete this;
98 }
99
100 virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
101 virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
102 virtual void * get_untyped_deleter() = 0;
103
104 void add_ref_copy()
105 {
106 atomic_increment( &use_count_ );
107 }
108
109 bool add_ref_lock() // true on success
110 {
111 return atomic_conditional_increment( &use_count_ ) != 0;
112 }
113
114 void release() // nothrow
115 {
116 if( atomic_decrement( &use_count_ ) == 1 )
117 {
118 dispose();
119 weak_release();
120 }
121 }
122
123 void weak_add_ref() // nothrow
124 {
125 atomic_increment( &weak_count_ );
126 }
127
128 void weak_release() // nothrow
129 {
130 if( atomic_decrement( &weak_count_ ) == 1 )
131 {
132 destroy();
133 }
134 }
135
136 long use_count() const // nothrow
137 {
138 return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
139 }
140};
141
142#if defined(__clang__)
143# pragma clang diagnostic pop
144#endif
145
146} // namespace detail
147
148} // namespace boost
149
150#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
151