CodeMover prototype
[dyninst.git] / external / boost / detail / sp_counted_base_gcc_sparc.hpp
1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED\r
2 #define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_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_gcc_sparc.hpp - g++ on Sparc V8+\r
11 //\r
12 //  Copyright (c) 2006 Piotr Wyderski\r
13 //  Copyright (c) 2006 Tomas Puverle\r
14 //  Copyright (c) 2006 Peter Dimov\r
15 //\r
16 //  Distributed under the Boost Software License, Version 1.0.\r
17 //  See accompanying file LICENSE_1_0.txt or copy at\r
18 //  http://www.boost.org/LICENSE_1_0.txt\r
19 //\r
20 //  Thanks to Michael van der Westhuizen\r
21 \r
22 #include <boost/detail/sp_typeinfo.hpp>\r
23 #include <inttypes.h> // int32_t\r
24 \r
25 namespace boost\r
26 {\r
27 \r
28 namespace detail\r
29 {\r
30 \r
31 inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ )\r
32 {\r
33     __asm__ __volatile__( "cas %0, %2, %1"\r
34                         : "+m" (*dest_), "+r" (swap_)\r
35                         : "r" (compare_)\r
36                         : "memory" );\r
37 \r
38     return swap_;\r
39 }\r
40 \r
41 inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv )\r
42 {\r
43     // long r = *pw;\r
44     // *pw += dv;\r
45     // return r;\r
46 \r
47     for( ;; )\r
48     {\r
49         int32_t r = *pw;\r
50 \r
51         if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )\r
52         {\r
53             return r;\r
54         }\r
55     }\r
56 }\r
57 \r
58 inline void atomic_increment( int32_t * pw )\r
59 {\r
60     atomic_fetch_and_add( pw, 1 );\r
61 }\r
62 \r
63 inline int32_t atomic_decrement( int32_t * pw )\r
64 {\r
65     return atomic_fetch_and_add( pw, -1 );\r
66 }\r
67 \r
68 inline int32_t atomic_conditional_increment( int32_t * pw )\r
69 {\r
70     // long r = *pw;\r
71     // if( r != 0 ) ++*pw;\r
72     // return r;\r
73 \r
74     for( ;; )\r
75     {\r
76         int32_t r = *pw;\r
77 \r
78         if( r == 0 )\r
79         {\r
80             return r;\r
81         }\r
82 \r
83         if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )\r
84         {\r
85             return r;\r
86         }\r
87     }    \r
88 }\r
89 \r
90 class sp_counted_base\r
91 {\r
92 private:\r
93 \r
94     sp_counted_base( sp_counted_base const & );\r
95     sp_counted_base & operator= ( sp_counted_base const & );\r
96 \r
97     int32_t use_count_;        // #shared\r
98     int32_t weak_count_;       // #weak + (#shared != 0)\r
99 \r
100 public:\r
101 \r
102     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
103     {\r
104     }\r
105 \r
106     virtual ~sp_counted_base() // nothrow\r
107     {\r
108     }\r
109 \r
110     // dispose() is called when use_count_ drops to zero, to release\r
111     // the resources managed by *this.\r
112 \r
113     virtual void dispose() = 0; // nothrow\r
114 \r
115     // destroy() is called when weak_count_ drops to zero.\r
116 \r
117     virtual void destroy() // nothrow\r
118     {\r
119         delete this;\r
120     }\r
121 \r
122     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
123 \r
124     void add_ref_copy()\r
125     {\r
126         atomic_increment( &use_count_ );\r
127     }\r
128 \r
129     bool add_ref_lock() // true on success\r
130     {\r
131         return atomic_conditional_increment( &use_count_ ) != 0;\r
132     }\r
133 \r
134     void release() // nothrow\r
135     {\r
136         if( atomic_decrement( &use_count_ ) == 1 )\r
137         {\r
138             dispose();\r
139             weak_release();\r
140         }\r
141     }\r
142 \r
143     void weak_add_ref() // nothrow\r
144     {\r
145         atomic_increment( &weak_count_ );\r
146     }\r
147 \r
148     void weak_release() // nothrow\r
149     {\r
150         if( atomic_decrement( &weak_count_ ) == 1 )\r
151         {\r
152             destroy();\r
153         }\r
154     }\r
155 \r
156     long use_count() const // nothrow\r
157     {\r
158         return const_cast< int32_t const volatile & >( use_count_ );\r
159     }\r
160 };\r
161 \r
162 } // namespace detail\r
163 \r
164 } // namespace boost\r
165 \r
166 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED\r