]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp
Update to boost 1.72
[lyx.git] / 3rdparty / boost / boost / smart_ptr / detail / sp_counted_base_spin.hpp
1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
2 #define BOOST_SMART_PTR_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 <boost/smart_ptr/detail/sp_typeinfo_.hpp>
22 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
23 #include <boost/config.hpp>
24
25 namespace boost
26 {
27
28 namespace detail
29 {
30
31 inline int atomic_exchange_and_add( int * pw, int dv )
32 {
33     spinlock_pool<1>::scoped_lock lock( pw );
34
35     int r = *pw;
36     *pw += dv;
37     return r;
38 }
39
40 inline void atomic_increment( int * pw )
41 {
42     spinlock_pool<1>::scoped_lock lock( pw );
43     ++*pw;
44 }
45
46 inline int atomic_conditional_increment( int * pw )
47 {
48     spinlock_pool<1>::scoped_lock lock( pw );
49
50     int rv = *pw;
51     if( rv != 0 ) ++*pw;
52     return rv;
53 }
54
55 class BOOST_SYMBOL_VISIBLE sp_counted_base
56 {
57 private:
58
59     sp_counted_base( sp_counted_base const & );
60     sp_counted_base & operator= ( sp_counted_base const & );
61
62     int use_count_;        // #shared
63     int weak_count_;       // #weak + (#shared != 0)
64
65 public:
66
67     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
68     {
69     }
70
71     virtual ~sp_counted_base() // nothrow
72     {
73     }
74
75     // dispose() is called when use_count_ drops to zero, to release
76     // the resources managed by *this.
77
78     virtual void dispose() = 0; // nothrow
79
80     // destroy() is called when weak_count_ drops to zero.
81
82     virtual void destroy() // nothrow
83     {
84         delete this;
85     }
86
87     virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
88     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
89     virtual void * get_untyped_deleter() = 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 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED