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 
21 namespace boost
22 {
23 
24 namespace detail
25 {
26 
27 typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
28 
atomic_increment(atomic_int_least32_t * pw)29 inline void atomic_increment( atomic_int_least32_t * pw )
30 {
31     __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
32 }
33 
atomic_decrement(atomic_int_least32_t * pw)34 inline 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 
atomic_conditional_increment(atomic_int_least32_t * pw)39 inline 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 
66 class sp_counted_base
67 {
68 private:
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 
76 public:
77 
sp_counted_base()78     sp_counted_base()
79     {
80         __c11_atomic_init( &use_count_, 1 );
81         __c11_atomic_init( &weak_count_, 1 );
82     }
83 
~sp_counted_base()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 
destroy()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 
add_ref_copy()104     void add_ref_copy()
105     {
106         atomic_increment( &use_count_ );
107     }
108 
add_ref_lock()109     bool add_ref_lock() // true on success
110     {
111         return atomic_conditional_increment( &use_count_ ) != 0;
112     }
113 
release()114     void release() // nothrow
115     {
116         if( atomic_decrement( &use_count_ ) == 1 )
117         {
118             dispose();
119             weak_release();
120         }
121     }
122 
weak_add_ref()123     void weak_add_ref() // nothrow
124     {
125         atomic_increment( &weak_count_ );
126     }
127 
weak_release()128     void weak_release() // nothrow
129     {
130         if( atomic_decrement( &weak_count_ ) == 1 )
131         {
132             destroy();
133         }
134     }
135 
use_count() const136     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