Fixes for VS 2008
[dyninst.git] / external / boost / detail / sp_counted_base_cw_ppc.hpp
1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED\r
2 #define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_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 //\r
11 //  detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC\r
12 //\r
13 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
14 //  Copyright 2004-2005 Peter Dimov\r
15 //\r
16 //  Distributed under the Boost Software License, Version 1.0. (See\r
17 //  accompanying file LICENSE_1_0.txt or copy at\r
18 //  http://www.boost.org/LICENSE_1_0.txt)\r
19 //\r
20 //\r
21 //  Lock-free algorithm by Alexander Terekhov\r
22 //\r
23 //  Thanks to Ben Hitchings for the #weak + (#shared != 0)\r
24 //  formulation\r
25 //\r
26 \r
27 #include <boost/detail/sp_typeinfo.hpp>\r
28 \r
29 namespace boost\r
30 {\r
31 \r
32 namespace detail\r
33 {\r
34 \r
35 inline void atomic_increment( register long * pw )\r
36 {\r
37     register int a;\r
38 \r
39     asm\r
40     {\r
41 loop:\r
42 \r
43     lwarx   a, 0, pw\r
44     addi    a, a, 1\r
45     stwcx.  a, 0, pw\r
46     bne-    loop\r
47     }\r
48 }\r
49 \r
50 inline long atomic_decrement( register long * pw )\r
51 {\r
52     register int a;\r
53 \r
54     asm\r
55     {\r
56     sync\r
57 \r
58 loop:\r
59 \r
60     lwarx   a, 0, pw\r
61     addi    a, a, -1\r
62     stwcx.  a, 0, pw\r
63     bne-    loop\r
64 \r
65     isync\r
66     }\r
67 \r
68     return a;\r
69 }\r
70 \r
71 inline long atomic_conditional_increment( register long * pw )\r
72 {\r
73     register int a;\r
74 \r
75     asm\r
76     {\r
77 loop:\r
78 \r
79     lwarx   a, 0, pw\r
80     cmpwi   a, 0\r
81     beq     store\r
82 \r
83     addi    a, a, 1\r
84 \r
85 store:\r
86 \r
87     stwcx.  a, 0, pw\r
88     bne-    loop\r
89     }\r
90 \r
91     return a;\r
92 }\r
93 \r
94 class sp_counted_base\r
95 {\r
96 private:\r
97 \r
98     sp_counted_base( sp_counted_base const & );\r
99     sp_counted_base & operator= ( sp_counted_base const & );\r
100 \r
101     long use_count_;        // #shared\r
102     long weak_count_;       // #weak + (#shared != 0)\r
103 \r
104 public:\r
105 \r
106     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
107     {\r
108     }\r
109 \r
110     virtual ~sp_counted_base() // nothrow\r
111     {\r
112     }\r
113 \r
114     // dispose() is called when use_count_ drops to zero, to release\r
115     // the resources managed by *this.\r
116 \r
117     virtual void dispose() = 0; // nothrow\r
118 \r
119     // destroy() is called when weak_count_ drops to zero.\r
120 \r
121     virtual void destroy() // nothrow\r
122     {\r
123         delete this;\r
124     }\r
125 \r
126     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
127 \r
128     void add_ref_copy()\r
129     {\r
130         atomic_increment( &use_count_ );\r
131     }\r
132 \r
133     bool add_ref_lock() // true on success\r
134     {\r
135         return atomic_conditional_increment( &use_count_ ) != 0;\r
136     }\r
137 \r
138     void release() // nothrow\r
139     {\r
140         if( atomic_decrement( &use_count_ ) == 0 )\r
141         {\r
142             dispose();\r
143             weak_release();\r
144         }\r
145     }\r
146 \r
147     void weak_add_ref() // nothrow\r
148     {\r
149         atomic_increment( &weak_count_ );\r
150     }\r
151 \r
152     void weak_release() // nothrow\r
153     {\r
154         if( atomic_decrement( &weak_count_ ) == 0 )\r
155         {\r
156             destroy();\r
157         }\r
158     }\r
159 \r
160     long use_count() const // nothrow\r
161     {\r
162         return static_cast<long const volatile &>( use_count_ );\r
163     }\r
164 };\r
165 \r
166 } // namespace detail\r
167 \r
168 } // namespace boost\r
169 \r
170 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED\r