fixing stuff
[dyninst.git] / dynutil / h / dyn_detail / boost / detail / sp_counted_base_spin.hpp
1 #ifndef DYN_DETAIL_BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
2 #define DYN_DETAIL_BOOST_DETAIL_SP_COUNTED_BASE_SPIN_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_spin.hpp - spinlock pool atomic emulation
12 //
13 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14 //  Copyright 2004-2008 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 #include <dyn_detail/boost/detail/sp_typeinfo.hpp>
22 #include <dyn_detail/boost/detail/spinlock_pool.hpp>
23
24 namespace dyn_detail
25 {
26
27 namespace boost
28 {
29
30 namespace detail
31 {
32
33 inline int atomic_exchange_and_add( int * pw, int dv )
34 {
35     spinlock_pool<1>::scoped_lock lock( pw );
36
37     int r = *pw;
38     *pw += dv;
39     return r;
40 }
41
42 inline void atomic_increment( int * pw )
43 {
44     spinlock_pool<1>::scoped_lock lock( pw );
45     ++*pw;
46 }
47
48 inline int atomic_conditional_increment( int * pw )
49 {
50     spinlock_pool<1>::scoped_lock lock( pw );
51
52     int rv = *pw;
53     if( rv != 0 ) ++*pw;
54     return rv;
55 }
56
57 class sp_counted_base
58 {
59 private:
60
61     sp_counted_base( sp_counted_base const & );
62     sp_counted_base & operator= ( sp_counted_base const & );
63
64     int use_count_;        // #shared
65     int weak_count_;       // #weak + (#shared != 0)
66
67 public:
68
69     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
70     {
71     }
72
73     virtual ~sp_counted_base() // nothrow
74     {
75     }
76
77     // dispose() is called when use_count_ drops to zero, to release
78     // the resources managed by *this.
79
80     virtual void dispose() = 0; // nothrow
81
82     // destroy() is called when weak_count_ drops to zero.
83
84     virtual void destroy() // nothrow
85     {
86         delete this;
87     }
88
89     virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
90
91     void add_ref_copy()
92     {
93         atomic_increment( &use_count_ );
94     }
95
96     bool add_ref_lock() // true on success
97     {
98         return atomic_conditional_increment( &use_count_ ) != 0;
99     }
100
101     void release() // nothrow
102     {
103         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
104         {
105             dispose();
106             weak_release();
107         }
108     }
109
110     void weak_add_ref() // nothrow
111     {
112         atomic_increment( &weak_count_ );
113     }
114
115     void weak_release() // nothrow
116     {
117         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
118         {
119             destroy();
120         }
121     }
122
123     long use_count() const // nothrow
124     {
125         spinlock_pool<1>::scoped_lock lock( &use_count_ );
126         return use_count_;
127     }
128 };
129
130 } // namespace detail
131
132 } // namespace boost
133  
134 } // namespace dyn_detail
135
136 #endif  // #ifndef DYN_DETAIL_BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED