source: NonGTP/Boost/boost/detail/sp_counted_base_w32.hpp @ 857

Revision 857, 2.6 KB checked in by igarcia, 18 years ago (diff)
Line 
1#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
2#define BOOST_DETAIL_SP_COUNTED_BASE_W32_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_w32.hpp
12//
13//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14//  Copyright 2004-2005 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//  Lock-free algorithm by Alexander Terekhov
22//
23//  Thanks to Ben Hitchings for the #weak + (#shared != 0)
24//  formulation
25//
26
27#include <boost/detail/interlocked.hpp>
28#include <typeinfo>
29
30namespace boost
31{
32
33namespace detail
34{
35
36class sp_counted_base
37{
38private:
39
40    sp_counted_base( sp_counted_base const & );
41    sp_counted_base & operator= ( sp_counted_base const & );
42
43    long use_count_;        // #shared
44    long weak_count_;       // #weak + (#shared != 0)
45
46public:
47
48    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
49    {
50    }
51
52    virtual ~sp_counted_base() // nothrow
53    {
54    }
55
56    // dispose() is called when use_count_ drops to zero, to release
57    // the resources managed by *this.
58
59    virtual void dispose() = 0; // nothrow
60
61    // destroy() is called when weak_count_ drops to zero.
62
63    virtual void destroy() // nothrow
64    {
65        delete this;
66    }
67
68    virtual void * get_deleter( std::type_info const & ti ) = 0;
69
70    void add_ref_copy()
71    {
72        BOOST_INTERLOCKED_INCREMENT( &use_count_ );
73    }
74
75    bool add_ref_lock() // true on success
76    {
77        for( ;; )
78        {
79            long tmp = static_cast< long const volatile& >( use_count_ );
80            if( tmp == 0 ) return false;
81            if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
82        }
83    }
84
85    void release() // nothrow
86    {
87        if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
88        {
89            dispose();
90            weak_release();
91        }
92    }
93
94    void weak_add_ref() // nothrow
95    {
96        BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
97    }
98
99    void weak_release() // nothrow
100    {
101        if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
102        {
103            destroy();
104        }
105    }
106
107    long use_count() const // nothrow
108    {
109        return static_cast<long const volatile &>( use_count_ );
110    }
111};
112
113} // namespace detail
114
115} // namespace boost
116
117#endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.