CodeMover prototype
[dyninst.git] / external / boost / detail / sp_counted_base_sync.hpp
1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r
2 #define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r
3 \r
4 // MS compatible compilers support #pragma once\r
5 \r
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
7 # pragma once\r
8 #endif\r
9 \r
10 //  detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics\r
11 //\r
12 //  Copyright (c) 2007 Peter Dimov\r
13 //\r
14 //  Distributed under the Boost Software License, Version 1.0.\r
15 //  See accompanying file LICENSE_1_0.txt or copy at\r
16 //  http://www.boost.org/LICENSE_1_0.txt\r
17 \r
18 #include <boost/detail/sp_typeinfo.hpp>\r
19 #include <limits.h>\r
20 \r
21 #if defined( __ia64__ ) && defined( __INTEL_COMPILER )\r
22 # include <ia64intrin.h>\r
23 #endif\r
24 \r
25 namespace boost\r
26 {\r
27 \r
28 namespace detail\r
29 {\r
30 \r
31 #if INT_MAX >= 2147483647\r
32 \r
33 typedef int sp_int32_t;\r
34 \r
35 #else\r
36 \r
37 typedef long sp_int32_t;\r
38 \r
39 #endif\r
40 \r
41 inline void atomic_increment( sp_int32_t * pw )\r
42 {\r
43     __sync_fetch_and_add( pw, 1 );\r
44 }\r
45 \r
46 inline sp_int32_t atomic_decrement( sp_int32_t * pw )\r
47 {\r
48     return __sync_fetch_and_add( pw, -1 );\r
49 }\r
50 \r
51 inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )\r
52 {\r
53     // long r = *pw;\r
54     // if( r != 0 ) ++*pw;\r
55     // return r;\r
56 \r
57     sp_int32_t r = *pw;\r
58 \r
59     for( ;; )\r
60     {\r
61         if( r == 0 )\r
62         {\r
63             return r;\r
64         }\r
65 \r
66         sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 );\r
67 \r
68         if( r2 == r )\r
69         {\r
70             return r;\r
71         }\r
72         else\r
73         {\r
74             r = r2;\r
75         }\r
76     }    \r
77 }\r
78 \r
79 class sp_counted_base\r
80 {\r
81 private:\r
82 \r
83     sp_counted_base( sp_counted_base const & );\r
84     sp_counted_base & operator= ( sp_counted_base const & );\r
85 \r
86     sp_int32_t use_count_;        // #shared\r
87     sp_int32_t weak_count_;       // #weak + (#shared != 0)\r
88 \r
89 public:\r
90 \r
91     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
92     {\r
93     }\r
94 \r
95     virtual ~sp_counted_base() // nothrow\r
96     {\r
97     }\r
98 \r
99     // dispose() is called when use_count_ drops to zero, to release\r
100     // the resources managed by *this.\r
101 \r
102     virtual void dispose() = 0; // nothrow\r
103 \r
104     // destroy() is called when weak_count_ drops to zero.\r
105 \r
106     virtual void destroy() // nothrow\r
107     {\r
108         delete this;\r
109     }\r
110 \r
111     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
112 \r
113     void add_ref_copy()\r
114     {\r
115         atomic_increment( &use_count_ );\r
116     }\r
117 \r
118     bool add_ref_lock() // true on success\r
119     {\r
120         return atomic_conditional_increment( &use_count_ ) != 0;\r
121     }\r
122 \r
123     void release() // nothrow\r
124     {\r
125         if( atomic_decrement( &use_count_ ) == 1 )\r
126         {\r
127             dispose();\r
128             weak_release();\r
129         }\r
130     }\r
131 \r
132     void weak_add_ref() // nothrow\r
133     {\r
134         atomic_increment( &weak_count_ );\r
135     }\r
136 \r
137     void weak_release() // nothrow\r
138     {\r
139         if( atomic_decrement( &weak_count_ ) == 1 )\r
140         {\r
141             destroy();\r
142         }\r
143     }\r
144 \r
145     long use_count() const // nothrow\r
146     {\r
147         return const_cast< sp_int32_t const volatile & >( use_count_ );\r
148     }\r
149 };\r
150 \r
151 } // namespace detail\r
152 \r
153 } // namespace boost\r
154 \r
155 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r