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 atomic_flag_implboost::atomics::detail::atomic_flag_impl60 BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic_flag_impl() BOOST_NOEXCEPT : m_storage(0u) 61 { 62 } 63 is_lock_freeboost::atomics::detail::atomic_flag_impl64 BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT 65 { 66 return is_always_lock_free; 67 } 68 has_native_wait_notifyboost::atomics::detail::atomic_flag_impl69 BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT 70 { 71 return wait_operations::has_native_wait_notify(m_storage); 72 } 73 testboost::atomics::detail::atomic_flag_impl74 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 test_and_setboost::atomics::detail::atomic_flag_impl81 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 clearboost::atomics::detail::atomic_flag_impl86 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 waitboost::atomics::detail::atomic_flag_impl94 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 notify_oneboost::atomics::detail::atomic_flag_impl102 BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT 103 { 104 wait_operations::notify_one(m_storage); 105 } 106 notify_allboost::atomics::detail::atomic_flag_impl107 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_ 130