source: NonGTP/Boost/boost/detail/sp_counted_base_cw_x86.hpp @ 857

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