1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
2 #define BOOST_SMART_PTR_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 <boost/detail/sp_typeinfo.hpp>
29 #include <boost/config.hpp>
30 
31 namespace boost
32 {
33 
34 namespace detail
35 {
36 
atomic_exchange_and_add(int * pw,int dv)37 inline int atomic_exchange_and_add( int * pw, int dv )
38 {
39     // int r = *pw;
40     // *pw += dv;
41     // return r;
42 
43     asm
44     {
45         mov esi, [pw]
46         mov eax, dv
47         lock xadd dword ptr [esi], eax
48     }
49 }
50 
atomic_increment(int * pw)51 inline void atomic_increment( int * pw )
52 {
53     //atomic_exchange_and_add( pw, 1 );
54 
55     asm
56     {
57         mov esi, [pw]
58         lock inc dword ptr [esi]
59     }
60 }
61 
atomic_conditional_increment(int * pw)62 inline int atomic_conditional_increment( int * pw )
63 {
64     // int rv = *pw;
65     // if( rv != 0 ) ++*pw;
66     // return rv;
67 
68     asm
69     {
70         mov esi, [pw]
71         mov eax, dword ptr [esi]
72     L0:
73         test eax, eax
74         je L1
75         mov ebx, eax
76         inc ebx
77         lock cmpxchg dword ptr [esi], ebx
78         jne L0
79     L1:
80     }
81 }
82 
83 class BOOST_SYMBOL_VISIBLE sp_counted_base
84 {
85 private:
86 
87     sp_counted_base( sp_counted_base const & );
88     sp_counted_base & operator= ( sp_counted_base const & );
89 
90     int use_count_;        // #shared
91     int weak_count_;       // #weak + (#shared != 0)
92 
93 public:
94 
sp_counted_base()95     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
96     {
97     }
98 
~sp_counted_base()99     virtual ~sp_counted_base() // nothrow
100     {
101     }
102 
103     // dispose() is called when use_count_ drops to zero, to release
104     // the resources managed by *this.
105 
106     virtual void dispose() = 0; // nothrow
107 
108     // destroy() is called when weak_count_ drops to zero.
109 
destroy()110     virtual void destroy() // nothrow
111     {
112         delete this;
113     }
114 
115     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
116     virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
117     virtual void * get_untyped_deleter() = 0;
118 
add_ref_copy()119     void add_ref_copy()
120     {
121         atomic_increment( &use_count_ );
122     }
123 
add_ref_lock()124     bool add_ref_lock() // true on success
125     {
126         return atomic_conditional_increment( &use_count_ ) != 0;
127     }
128 
release()129     void release() // nothrow
130     {
131         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
132         {
133             dispose();
134             weak_release();
135         }
136     }
137 
weak_add_ref()138     void weak_add_ref() // nothrow
139     {
140         atomic_increment( &weak_count_ );
141     }
142 
weak_release()143     void weak_release() // nothrow
144     {
145         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
146         {
147             destroy();
148         }
149     }
150 
use_count() const151     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 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
162