CodeMover prototype
[dyninst.git] / external / boost / detail / sp_counted_base_acc_ia64.hpp
1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r
2 #define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r
3 \r
4 //\r
5 //  detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64\r
6 //\r
7 //  Copyright 2007 Baruch Zilber\r
8 //  Copyright 2007 Boris Gubenko\r
9 //\r
10 //  Distributed under the Boost Software License, Version 1.0. (See\r
11 //  accompanying file LICENSE_1_0.txt or copy at\r
12 //  http://www.boost.org/LICENSE_1_0.txt)\r
13 //\r
14 //\r
15 //  Lock-free algorithm by Alexander Terekhov\r
16 //\r
17 \r
18 #include <boost/detail/sp_typeinfo.hpp>\r
19 #include <machine/sys/inline.h>\r
20 \r
21 namespace boost\r
22 {\r
23 \r
24 namespace detail\r
25 {\r
26 \r
27 inline void atomic_increment( int * pw )\r
28 {\r
29     // ++*pw;\r
30 \r
31     _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE);\r
32\r
33 \r
34 inline int atomic_decrement( int * pw )\r
35 {\r
36     // return --*pw;\r
37 \r
38     int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE));\r
39     if (1 == r)\r
40     {\r
41         _Asm_mf();\r
42     }\r
43     \r
44     return r - 1;\r
45 }\r
46 \r
47 inline int atomic_conditional_increment( int * pw )\r
48 {\r
49     // if( *pw != 0 ) ++*pw;\r
50     // return *pw;\r
51 \r
52     int v = *pw;\r
53     \r
54     for (;;)\r
55     {\r
56         if (0 == v)\r
57         {\r
58             return 0;\r
59         }\r
60         \r
61         _Asm_mov_to_ar(_AREG_CCV,\r
62                        v,\r
63                        (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE));\r
64         int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE));\r
65         if (r == v)\r
66         {\r
67             return r + 1;\r
68         }\r
69         \r
70         v = r;\r
71     }\r
72 }\r
73 \r
74 class sp_counted_base\r
75 {\r
76 private:\r
77 \r
78     sp_counted_base( sp_counted_base const & );\r
79     sp_counted_base & operator= ( sp_counted_base const & );\r
80 \r
81     int use_count_;        // #shared\r
82     int weak_count_;       // #weak + (#shared != 0)\r
83 \r
84 public:\r
85 \r
86     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
87     {\r
88     }\r
89 \r
90     virtual ~sp_counted_base() // nothrow\r
91     {\r
92     }\r
93 \r
94     // dispose() is called when use_count_ drops to zero, to release\r
95     // the resources managed by *this.\r
96 \r
97     virtual void dispose() = 0; // nothrow\r
98 \r
99     // destroy() is called when weak_count_ drops to zero.\r
100 \r
101     virtual void destroy() // nothrow\r
102     {\r
103         delete this;\r
104     }\r
105 \r
106     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
107 \r
108     void add_ref_copy()\r
109     {\r
110         atomic_increment( &use_count_ );\r
111     }\r
112 \r
113     bool add_ref_lock() // true on success\r
114     {\r
115         return atomic_conditional_increment( &use_count_ ) != 0;\r
116     }\r
117 \r
118     void release() // nothrow\r
119     {\r
120         if( atomic_decrement( &use_count_ ) == 0 )\r
121         {\r
122             dispose();\r
123             weak_release();\r
124         }\r
125     }\r
126 \r
127     void weak_add_ref() // nothrow\r
128     {\r
129         atomic_increment( &weak_count_ );\r
130     }\r
131 \r
132     void weak_release() // nothrow\r
133     {\r
134         if( atomic_decrement( &weak_count_ ) == 0 )\r
135         {\r
136             destroy();\r
137         }\r
138     }\r
139 \r
140     long use_count() const // nothrow\r
141     {\r
142         return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here\r
143     }\r
144 };\r
145 \r
146 } // namespace detail\r
147 \r
148 } // namespace boost\r
149 \r
150 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r