Fixes for VS 2008
[dyninst.git] / external / boost / detail / sp_counted_base_spin.hpp
1 #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r
2 #define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r
3 \r
4 // MS compatible compilers support #pragma once\r
5 \r
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
7 # pragma once\r
8 #endif\r
9 \r
10 //\r
11 //  detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation\r
12 //\r
13 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
14 //  Copyright 2004-2008 Peter Dimov\r
15 //\r
16 //  Distributed under the Boost Software License, Version 1.0. (See\r
17 //  accompanying file LICENSE_1_0.txt or copy at\r
18 //  http://www.boost.org/LICENSE_1_0.txt)\r
19 //\r
20 \r
21 #include <boost/detail/sp_typeinfo.hpp>\r
22 #include <boost/detail/spinlock_pool.hpp>\r
23 \r
24 namespace boost\r
25 {\r
26 \r
27 namespace detail\r
28 {\r
29 \r
30 inline int atomic_exchange_and_add( int * pw, int dv )\r
31 {\r
32     spinlock_pool<1>::scoped_lock lock( pw );\r
33 \r
34     int r = *pw;\r
35     *pw += dv;\r
36     return r;\r
37 }\r
38 \r
39 inline void atomic_increment( int * pw )\r
40 {\r
41     spinlock_pool<1>::scoped_lock lock( pw );\r
42     ++*pw;\r
43 }\r
44 \r
45 inline int atomic_conditional_increment( int * pw )\r
46 {\r
47     spinlock_pool<1>::scoped_lock lock( pw );\r
48 \r
49     int rv = *pw;\r
50     if( rv != 0 ) ++*pw;\r
51     return rv;\r
52 }\r
53 \r
54 class sp_counted_base\r
55 {\r
56 private:\r
57 \r
58     sp_counted_base( sp_counted_base const & );\r
59     sp_counted_base & operator= ( sp_counted_base const & );\r
60 \r
61     int use_count_;        // #shared\r
62     int weak_count_;       // #weak + (#shared != 0)\r
63 \r
64 public:\r
65 \r
66     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
67     {\r
68     }\r
69 \r
70     virtual ~sp_counted_base() // nothrow\r
71     {\r
72     }\r
73 \r
74     // dispose() is called when use_count_ drops to zero, to release\r
75     // the resources managed by *this.\r
76 \r
77     virtual void dispose() = 0; // nothrow\r
78 \r
79     // destroy() is called when weak_count_ drops to zero.\r
80 \r
81     virtual void destroy() // nothrow\r
82     {\r
83         delete this;\r
84     }\r
85 \r
86     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
87 \r
88     void add_ref_copy()\r
89     {\r
90         atomic_increment( &use_count_ );\r
91     }\r
92 \r
93     bool add_ref_lock() // true on success\r
94     {\r
95         return atomic_conditional_increment( &use_count_ ) != 0;\r
96     }\r
97 \r
98     void release() // nothrow\r
99     {\r
100         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )\r
101         {\r
102             dispose();\r
103             weak_release();\r
104         }\r
105     }\r
106 \r
107     void weak_add_ref() // nothrow\r
108     {\r
109         atomic_increment( &weak_count_ );\r
110     }\r
111 \r
112     void weak_release() // nothrow\r
113     {\r
114         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )\r
115         {\r
116             destroy();\r
117         }\r
118     }\r
119 \r
120     long use_count() const // nothrow\r
121     {\r
122         spinlock_pool<1>::scoped_lock lock( &use_count_ );\r
123         return use_count_;\r
124     }\r
125 };\r
126 \r
127 } // namespace detail\r
128 \r
129 } // namespace boost\r
130 \r
131 #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r