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