summaryrefslogtreecommitdiff
path: root/boost/smart_ptr/atomic_shared_ptr.hpp
blob: d1efa8e28031f5a11f55065b706fd647cc368463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED

//
//  atomic_shared_ptr.hpp
//
//  Copyright 2017 Peter Dimov
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  See http://www.boost.org/libs/smart_ptr/ for documentation.
//

#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>
#include <cstring>

namespace boost
{

template<class T> class atomic_shared_ptr
{
private:

    boost::shared_ptr<T> p_;

    mutable boost::detail::spinlock l_;

    atomic_shared_ptr(const atomic_shared_ptr&);
    atomic_shared_ptr& operator=(const atomic_shared_ptr&);

private:

    bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
    {
        l_.lock();

        if( p_._internal_equiv( v ) )
        {
            p_.swap( w );

            l_.unlock();
            return true;
        }
        else
        {
            shared_ptr<T> tmp( p_ );

            l_.unlock();

            tmp.swap( v );
            return false;
        }
    }

public:

#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )

    constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
    {
    }

#else

    atomic_shared_ptr() BOOST_SP_NOEXCEPT
    {
        boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
        std::memcpy( &l_, &init, sizeof( init ) );
    }

#endif

    atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
        : p_( std::move( p ) )
#else
        : p_( p )
#endif
    {
        boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
        std::memcpy( &l_, &init, sizeof( init ) );
    }

    atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
    {
        boost::detail::spinlock::scoped_lock lock( l_ );
        p_.swap( r );

        return *this;
    }

    BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
    {
        return false;
    }

    shared_ptr<T> load( int = 0 ) const BOOST_SP_NOEXCEPT
    {
        boost::detail::spinlock::scoped_lock lock( l_ );
        return p_;
    }

    operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
    {
        boost::detail::spinlock::scoped_lock lock( l_ );
        return p_;
    }

    void store( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
    {
        boost::detail::spinlock::scoped_lock lock( l_ );
        p_.swap( r );
    }

    shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
    {
        {
            boost::detail::spinlock::scoped_lock lock( l_ );
            p_.swap( r );
        }

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

        return std::move( r );

#else

        return r;

#endif
    }

    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, w );
    }

    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, w );
    }

    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, w );
    }

    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, w );
    }

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, std::move( w ) );
    }

    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, std::move( w ) );
    }

    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, std::move( w ) );
    }

    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
    {
        return compare_exchange( v, std::move( w ) );
    }

#endif
};

} // namespace boost

#endif  // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED