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

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