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