liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
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
/*
 * 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)
 *
 * Copyright (c) 2020 Andrey Semashev
 */
/*!
 * \file   atomic/detail/wait_ops_generic.hpp
 *
 * This header contains generic (lock-based) implementation of the waiting/notifying atomic operations.
 */
 
#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_
 
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/pause.hpp>
#include <boost/atomic/detail/lock_pool.hpp>
#include <boost/atomic/detail/wait_operations_fwd.hpp>
#include <boost/atomic/detail/header.hpp>
 
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
 
namespace boost {
namespace atomics {
namespace detail {
 
//! Generic implementation of waiting/notifying operations
template< typename Base, bool Interprocess >
struct wait_operations_generic;
 
template< typename Base >
struct wait_operations_generic< Base, false > :
    public Base
{
    typedef Base base_type;
    typedef typename base_type::storage_type storage_type;
    typedef lock_pool::scoped_lock< base_type::storage_alignment, true > scoped_lock;
    typedef lock_pool::scoped_wait_state< base_type::storage_alignment > scoped_wait_state;
 
    static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false;
 
    static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT
    {
        return false;
    }
 
    static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT
    {
        storage_type new_val = base_type::load(storage, order);
        if (new_val == old_val)
        {
            scoped_wait_state wait_state(&storage);
            new_val = base_type::load(storage, order);
            while (new_val == old_val)
            {
                wait_state.wait();
                new_val = base_type::load(storage, order);
            }
        }
 
        return new_val;
    }
 
    static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT
    {
        scoped_lock lock(&storage);
        lock_pool::notify_one(lock.get_lock_state(), &storage);
    }
 
    static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT
    {
        scoped_lock lock(&storage);
        lock_pool::notify_all(lock.get_lock_state(), &storage);
    }
};
 
template< typename Base >
struct wait_operations_generic< Base, true > :
    public Base
{
    typedef Base base_type;
    typedef typename base_type::storage_type storage_type;
 
    static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false;
 
    static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT
    {
        return false;
    }
 
    static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT
    {
        storage_type new_val = base_type::load(storage, order);
        if (new_val == old_val)
        {
            for (unsigned int i = 0u; i < 16u; ++i)
            {
                atomics::detail::pause();
                new_val = base_type::load(storage, order);
                if (new_val != old_val)
                    goto finish;
            }
 
            do
            {
                atomics::detail::wait_some();
                new_val = base_type::load(storage, order);
            }
            while (new_val == old_val);
        }
 
    finish:
        return new_val;
    }
 
    static BOOST_FORCEINLINE void notify_one(storage_type volatile&) BOOST_NOEXCEPT
    {
    }
 
    static BOOST_FORCEINLINE void notify_all(storage_type volatile&) BOOST_NOEXCEPT
    {
    }
};
 
template< typename Base, std::size_t Size, bool Interprocess >
struct wait_operations< Base, Size, true, Interprocess > :
    public wait_operations_generic< Base, Interprocess >
{
};
 
} // namespace detail
} // namespace atomics
} // namespace boost
 
#include <boost/atomic/detail/footer.hpp>
 
#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_