]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED |
2 | #define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_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_mips.hpp - g++ on MIPS | |
12 | // | |
13 | // Copyright (c) 2009, Spirent Communications, Inc. | |
14 | // | |
15 | // Distributed under the Boost Software License, Version 1.0. (See | |
16 | // accompanying file LICENSE_1_0.txt or copy at | |
17 | // http://www.boost.org/LICENSE_1_0.txt) | |
18 | // | |
19 | // | |
20 | // Lock-free algorithm by Alexander Terekhov | |
21 | // | |
22 | ||
92f5a8d4 TL |
23 | #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> |
24 | #include <boost/config.hpp> | |
7c673cae FG |
25 | |
26 | namespace boost | |
27 | { | |
28 | ||
29 | namespace detail | |
30 | { | |
31 | ||
32 | inline void atomic_increment( int * pw ) | |
33 | { | |
34 | // ++*pw; | |
35 | ||
36 | int tmp; | |
37 | ||
38 | __asm__ __volatile__ | |
39 | ( | |
40 | "0:\n\t" | |
41 | ".set push\n\t" | |
11fdf7f2 | 42 | #if !defined(__mips_isa_rev) || (__mips_isa_rev < 6) |
7c673cae | 43 | ".set mips2\n\t" |
11fdf7f2 | 44 | #endif |
7c673cae FG |
45 | "ll %0, %1\n\t" |
46 | "addiu %0, 1\n\t" | |
47 | "sc %0, %1\n\t" | |
48 | ".set pop\n\t" | |
49 | "beqz %0, 0b": | |
50 | "=&r"( tmp ), "=m"( *pw ): | |
51 | "m"( *pw ) | |
52 | ); | |
53 | } | |
54 | ||
55 | inline int atomic_decrement( int * pw ) | |
56 | { | |
57 | // return --*pw; | |
58 | ||
59 | int rv, tmp; | |
60 | ||
61 | __asm__ __volatile__ | |
62 | ( | |
63 | "0:\n\t" | |
64 | ".set push\n\t" | |
11fdf7f2 | 65 | #if !defined(__mips_isa_rev) || (__mips_isa_rev < 6) |
7c673cae | 66 | ".set mips2\n\t" |
11fdf7f2 | 67 | #endif |
7c673cae FG |
68 | "ll %1, %2\n\t" |
69 | "addiu %0, %1, -1\n\t" | |
70 | "sc %0, %2\n\t" | |
71 | ".set pop\n\t" | |
72 | "beqz %0, 0b\n\t" | |
73 | "addiu %0, %1, -1": | |
74 | "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): | |
75 | "m"( *pw ): | |
76 | "memory" | |
77 | ); | |
78 | ||
79 | return rv; | |
80 | } | |
81 | ||
82 | inline int atomic_conditional_increment( int * pw ) | |
83 | { | |
84 | // if( *pw != 0 ) ++*pw; | |
85 | // return *pw; | |
86 | ||
87 | int rv, tmp; | |
88 | ||
89 | __asm__ __volatile__ | |
90 | ( | |
91 | "0:\n\t" | |
92 | ".set push\n\t" | |
11fdf7f2 | 93 | #if !defined(__mips_isa_rev) || (__mips_isa_rev < 6) |
7c673cae | 94 | ".set mips2\n\t" |
11fdf7f2 | 95 | #endif |
7c673cae FG |
96 | "ll %0, %2\n\t" |
97 | "beqz %0, 1f\n\t" | |
98 | "addiu %1, %0, 1\n\t" | |
99 | "sc %1, %2\n\t" | |
100 | ".set pop\n\t" | |
101 | "beqz %1, 0b\n\t" | |
102 | "addiu %0, %0, 1\n\t" | |
103 | "1:": | |
104 | "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): | |
105 | "m"( *pw ): | |
106 | "memory" | |
107 | ); | |
108 | ||
109 | return rv; | |
110 | } | |
111 | ||
92f5a8d4 | 112 | class BOOST_SYMBOL_VISIBLE sp_counted_base |
7c673cae FG |
113 | { |
114 | private: | |
115 | ||
116 | sp_counted_base( sp_counted_base const & ); | |
117 | sp_counted_base & operator= ( sp_counted_base const & ); | |
118 | ||
119 | int use_count_; // #shared | |
120 | int weak_count_; // #weak + (#shared != 0) | |
121 | ||
122 | public: | |
123 | ||
124 | sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) | |
125 | { | |
126 | } | |
127 | ||
128 | virtual ~sp_counted_base() // nothrow | |
129 | { | |
130 | } | |
131 | ||
132 | // dispose() is called when use_count_ drops to zero, to release | |
133 | // the resources managed by *this. | |
134 | ||
135 | virtual void dispose() = 0; // nothrow | |
136 | ||
137 | // destroy() is called when weak_count_ drops to zero. | |
138 | ||
139 | virtual void destroy() // nothrow | |
140 | { | |
141 | delete this; | |
142 | } | |
143 | ||
92f5a8d4 TL |
144 | virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; |
145 | virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; | |
7c673cae FG |
146 | virtual void * get_untyped_deleter() = 0; |
147 | ||
148 | void add_ref_copy() | |
149 | { | |
150 | atomic_increment( &use_count_ ); | |
151 | } | |
152 | ||
153 | bool add_ref_lock() // true on success | |
154 | { | |
155 | return atomic_conditional_increment( &use_count_ ) != 0; | |
156 | } | |
157 | ||
158 | void release() // nothrow | |
159 | { | |
160 | if( atomic_decrement( &use_count_ ) == 0 ) | |
161 | { | |
162 | dispose(); | |
163 | weak_release(); | |
164 | } | |
165 | } | |
166 | ||
167 | void weak_add_ref() // nothrow | |
168 | { | |
169 | atomic_increment( &weak_count_ ); | |
170 | } | |
171 | ||
172 | void weak_release() // nothrow | |
173 | { | |
174 | if( atomic_decrement( &weak_count_ ) == 0 ) | |
175 | { | |
176 | destroy(); | |
177 | } | |
178 | } | |
179 | ||
180 | long use_count() const // nothrow | |
181 | { | |
182 | return static_cast<int const volatile &>( use_count_ ); | |
183 | } | |
184 | }; | |
185 | ||
186 | } // namespace detail | |
187 | ||
188 | } // namespace boost | |
189 | ||
190 | #endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED |