1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_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_gcc_x86.hpp - g++ on 486+ or AMD64
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 <boost/detail/sp_typeinfo.hpp>
28 
29 namespace boost
30 {
31 
32 namespace detail
33 {
34 
atomic_exchange_and_add(int * pw,int dv)35 inline int atomic_exchange_and_add( int * pw, int dv )
36 {
37     // int r = *pw;
38     // *pw += dv;
39     // return r;
40 
41     int r;
42 
43     __asm__ __volatile__
44     (
45         "lock\n\t"
46         "xadd %1, %0":
47         "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
48         "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
49         "memory", "cc" // clobbers
50     );
51 
52     return r;
53 }
54 
atomic_increment(int * pw)55 inline void atomic_increment( int * pw )
56 {
57     //atomic_exchange_and_add( pw, 1 );
58 
59     __asm__
60     (
61         "lock\n\t"
62         "incl %0":
63         "=m"( *pw ): // output (%0)
64         "m"( *pw ): // input (%1)
65         "cc" // clobbers
66     );
67 }
68 
atomic_conditional_increment(int * pw)69 inline int atomic_conditional_increment( int * pw )
70 {
71     // int rv = *pw;
72     // if( rv != 0 ) ++*pw;
73     // return rv;
74 
75     int rv, tmp;
76 
77     __asm__
78     (
79         "movl %0, %%eax\n\t"
80         "0:\n\t"
81         "test %%eax, %%eax\n\t"
82         "je 1f\n\t"
83         "movl %%eax, %2\n\t"
84         "incl %2\n\t"
85         "lock\n\t"
86         "cmpxchgl %2, %0\n\t"
87         "jne 0b\n\t"
88         "1:":
89         "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
90         "m"( *pw ): // input (%3)
91         "cc" // clobbers
92     );
93 
94     return rv;
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     int use_count_;        // #shared
105     int weak_count_;       // #weak + (#shared != 0)
106 
107 public:
108 
sp_counted_base()109     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
110     {
111     }
112 
~sp_counted_base()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 
destroy()124     virtual void destroy() // nothrow
125     {
126         delete this;
127     }
128 
129     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
130     virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
131     virtual void * get_untyped_deleter() = 0;
132 
add_ref_copy()133     void add_ref_copy()
134     {
135         atomic_increment( &use_count_ );
136     }
137 
add_ref_lock()138     bool add_ref_lock() // true on success
139     {
140         return atomic_conditional_increment( &use_count_ ) != 0;
141     }
142 
release()143     void release() // nothrow
144     {
145         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
146         {
147             dispose();
148             weak_release();
149         }
150     }
151 
weak_add_ref()152     void weak_add_ref() // nothrow
153     {
154         atomic_increment( &weak_count_ );
155     }
156 
weak_release()157     void weak_release() // nothrow
158     {
159         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
160         {
161             destroy();
162         }
163     }
164 
use_count() const165     long use_count() const // nothrow
166     {
167         return static_cast<int const volatile &>( use_count_ );
168     }
169 };
170 
171 } // namespace detail
172 
173 } // namespace boost
174 
175 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
176