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