]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / smart_ptr / detail / sp_counted_base_spin.hpp
1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_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/sp_counted_base_spin.hpp - spinlock pool atomic emulation
12 //
13 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14 // Copyright 2004-2008 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/detail/sp_typeinfo_.hpp>
22 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
23 #include <boost/config.hpp>
24
25 #if defined(BOOST_SP_REPORT_IMPLEMENTATION)
26
27 #include <boost/config/pragma_message.hpp>
28 BOOST_PRAGMA_MESSAGE("Using spinlock-based sp_counted_base")
29
30 #endif
31
32 namespace boost
33 {
34
35 namespace detail
36 {
37
38 inline int atomic_exchange_and_add( int * pw, int dv )
39 {
40 spinlock_pool<1>::scoped_lock lock( pw );
41
42 int r = *pw;
43 *pw += dv;
44 return r;
45 }
46
47 inline void atomic_increment( int * pw )
48 {
49 spinlock_pool<1>::scoped_lock lock( pw );
50 ++*pw;
51 }
52
53 inline int atomic_conditional_increment( int * pw )
54 {
55 spinlock_pool<1>::scoped_lock lock( pw );
56
57 int rv = *pw;
58 if( rv != 0 ) ++*pw;
59 return rv;
60 }
61
62 class BOOST_SYMBOL_VISIBLE sp_counted_base
63 {
64 private:
65
66 sp_counted_base( sp_counted_base const & );
67 sp_counted_base & operator= ( sp_counted_base const & );
68
69 int use_count_; // #shared
70 int weak_count_; // #weak + (#shared != 0)
71
72 public:
73
74 sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
75 {
76 }
77
78 virtual ~sp_counted_base() // nothrow
79 {
80 }
81
82 // dispose() is called when use_count_ drops to zero, to release
83 // the resources managed by *this.
84
85 virtual void dispose() = 0; // nothrow
86
87 // destroy() is called when weak_count_ drops to zero.
88
89 virtual void destroy() // nothrow
90 {
91 delete this;
92 }
93
94 virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
95 virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
96 virtual void * get_untyped_deleter() = 0;
97
98 void add_ref_copy()
99 {
100 atomic_increment( &use_count_ );
101 }
102
103 bool add_ref_lock() // true on success
104 {
105 return atomic_conditional_increment( &use_count_ ) != 0;
106 }
107
108 void release() // nothrow
109 {
110 if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
111 {
112 dispose();
113 weak_release();
114 }
115 }
116
117 void weak_add_ref() // nothrow
118 {
119 atomic_increment( &weak_count_ );
120 }
121
122 void weak_release() // nothrow
123 {
124 if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
125 {
126 destroy();
127 }
128 }
129
130 long use_count() const // nothrow
131 {
132 spinlock_pool<1>::scoped_lock lock( &use_count_ );
133 return use_count_;
134 }
135 };
136
137 } // namespace detail
138
139 } // namespace boost
140
141 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED