]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | /* |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * Copyright (c) 2011 Helge Bahmann | |
7 | * Copyright (c) 2013 Tim Blechmann | |
8 | * Copyright (c) 2014, 2020 Andrey Semashev | |
9 | */ | |
10 | /*! | |
11 | * \file atomic/detail/atomic_flag_impl.hpp | |
12 | * | |
13 | * This header contains implementation of \c atomic_flag. | |
14 | */ | |
15 | ||
16 | #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ | |
17 | #define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ | |
18 | ||
19 | #include <boost/assert.hpp> | |
20 | #include <boost/memory_order.hpp> | |
21 | #include <boost/atomic/detail/config.hpp> | |
22 | #include <boost/atomic/detail/core_operations.hpp> | |
23 | #include <boost/atomic/detail/wait_operations.hpp> | |
24 | #include <boost/atomic/detail/aligned_variable.hpp> | |
25 | #include <boost/atomic/detail/header.hpp> | |
26 | ||
27 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
28 | #pragma once | |
29 | #endif | |
30 | ||
31 | /* | |
32 | * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, | |
33 | * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. | |
34 | */ | |
35 | ||
36 | namespace boost { | |
37 | namespace atomics { | |
38 | namespace detail { | |
39 | ||
40 | #if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) | |
41 | #define BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT | |
42 | #else | |
43 | #define BOOST_ATOMIC_FLAG_INIT {} | |
44 | #endif | |
45 | ||
46 | //! Atomic flag implementation | |
47 | template< bool IsInterprocess > | |
48 | struct atomic_flag_impl | |
49 | { | |
50 | // Prefer 4-byte storage as most platforms support waiting/notifying operations without a lock pool for 32-bit integers | |
51 | typedef atomics::detail::core_operations< 4u, false, IsInterprocess > core_operations; | |
52 | typedef atomics::detail::wait_operations< core_operations > wait_operations; | |
53 | typedef typename core_operations::storage_type storage_type; | |
54 | ||
55 | static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free; | |
56 | static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify; | |
57 | ||
58 | BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(core_operations::storage_alignment, storage_type, m_storage); | |
59 | ||
60 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic_flag_impl() BOOST_NOEXCEPT : m_storage(0u) | |
61 | { | |
62 | } | |
63 | ||
64 | BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT | |
65 | { | |
66 | return is_always_lock_free; | |
67 | } | |
68 | ||
69 | BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT | |
70 | { | |
71 | return wait_operations::has_native_wait_notify(m_storage); | |
72 | } | |
73 | ||
74 | BOOST_FORCEINLINE bool test(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT | |
75 | { | |
76 | BOOST_ASSERT(order != memory_order_release); | |
77 | BOOST_ASSERT(order != memory_order_acq_rel); | |
78 | return !!core_operations::load(m_storage, order); | |
79 | } | |
80 | ||
81 | BOOST_FORCEINLINE bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
82 | { | |
83 | return core_operations::test_and_set(m_storage, order); | |
84 | } | |
85 | ||
86 | BOOST_FORCEINLINE void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
87 | { | |
88 | BOOST_ASSERT(order != memory_order_consume); | |
89 | BOOST_ASSERT(order != memory_order_acquire); | |
90 | BOOST_ASSERT(order != memory_order_acq_rel); | |
91 | core_operations::clear(m_storage, order); | |
92 | } | |
93 | ||
94 | BOOST_FORCEINLINE bool wait(bool old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT | |
95 | { | |
96 | BOOST_ASSERT(order != memory_order_release); | |
97 | BOOST_ASSERT(order != memory_order_acq_rel); | |
98 | ||
99 | return !!wait_operations::wait(m_storage, static_cast< storage_type >(old_val), order); | |
100 | } | |
101 | ||
102 | BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT | |
103 | { | |
104 | wait_operations::notify_one(m_storage); | |
105 | } | |
106 | ||
107 | BOOST_FORCEINLINE void notify_all() volatile BOOST_NOEXCEPT | |
108 | { | |
109 | wait_operations::notify_all(m_storage); | |
110 | } | |
111 | ||
112 | BOOST_DELETED_FUNCTION(atomic_flag_impl(atomic_flag_impl const&)) | |
113 | BOOST_DELETED_FUNCTION(atomic_flag_impl& operator= (atomic_flag_impl const&)) | |
114 | }; | |
115 | ||
116 | #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) | |
117 | template< bool IsInterprocess > | |
118 | BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::is_always_lock_free; | |
119 | template< bool IsInterprocess > | |
120 | BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::always_has_native_wait_notify; | |
121 | #endif | |
122 | ||
123 | } // namespace detail | |
124 | } // namespace atomics | |
125 | } // namespace boost | |
126 | ||
127 | #include <boost/atomic/detail/footer.hpp> | |
128 | ||
129 | #endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ |