Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:58

0001 /*
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * Copyright (c) 2020 Andrey Semashev
0007  */
0008 /*!
0009  * \file   atomic/detail/wait_ops_generic.hpp
0010  *
0011  * This header contains generic (lock-based) implementation of the waiting/notifying atomic operations.
0012  */
0013 
0014 #ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_
0015 #define BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_
0016 
0017 #include <cstddef>
0018 #include <boost/memory_order.hpp>
0019 #include <boost/atomic/detail/config.hpp>
0020 #include <boost/atomic/detail/pause.hpp>
0021 #include <boost/atomic/detail/lock_pool.hpp>
0022 #include <boost/atomic/detail/wait_operations_fwd.hpp>
0023 #include <boost/atomic/detail/header.hpp>
0024 
0025 #ifdef BOOST_HAS_PRAGMA_ONCE
0026 #pragma once
0027 #endif
0028 
0029 namespace boost {
0030 namespace atomics {
0031 namespace detail {
0032 
0033 //! Generic implementation of waiting/notifying operations
0034 template< typename Base, bool Interprocess >
0035 struct wait_operations_generic;
0036 
0037 template< typename Base >
0038 struct wait_operations_generic< Base, false > :
0039     public Base
0040 {
0041     typedef Base base_type;
0042     typedef typename base_type::storage_type storage_type;
0043     typedef lock_pool::scoped_lock< base_type::storage_alignment, true > scoped_lock;
0044     typedef lock_pool::scoped_wait_state< base_type::storage_alignment > scoped_wait_state;
0045 
0046     static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false;
0047 
0048     static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT
0049     {
0050         return false;
0051     }
0052 
0053     static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT
0054     {
0055         storage_type new_val = base_type::load(storage, order);
0056         if (new_val == old_val)
0057         {
0058             scoped_wait_state wait_state(&storage);
0059             new_val = base_type::load(storage, order);
0060             while (new_val == old_val)
0061             {
0062                 wait_state.wait();
0063                 new_val = base_type::load(storage, order);
0064             }
0065         }
0066 
0067         return new_val;
0068     }
0069 
0070     static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT
0071     {
0072         scoped_lock lock(&storage);
0073         lock_pool::notify_one(lock.get_lock_state(), &storage);
0074     }
0075 
0076     static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT
0077     {
0078         scoped_lock lock(&storage);
0079         lock_pool::notify_all(lock.get_lock_state(), &storage);
0080     }
0081 };
0082 
0083 template< typename Base >
0084 struct wait_operations_generic< Base, true > :
0085     public Base
0086 {
0087     typedef Base base_type;
0088     typedef typename base_type::storage_type storage_type;
0089 
0090     static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false;
0091 
0092     static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT
0093     {
0094         return false;
0095     }
0096 
0097     static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT
0098     {
0099         storage_type new_val = base_type::load(storage, order);
0100         if (new_val == old_val)
0101         {
0102             for (unsigned int i = 0u; i < 16u; ++i)
0103             {
0104                 atomics::detail::pause();
0105                 new_val = base_type::load(storage, order);
0106                 if (new_val != old_val)
0107                     goto finish;
0108             }
0109 
0110             do
0111             {
0112                 atomics::detail::wait_some();
0113                 new_val = base_type::load(storage, order);
0114             }
0115             while (new_val == old_val);
0116         }
0117 
0118     finish:
0119         return new_val;
0120     }
0121 
0122     static BOOST_FORCEINLINE void notify_one(storage_type volatile&) BOOST_NOEXCEPT
0123     {
0124     }
0125 
0126     static BOOST_FORCEINLINE void notify_all(storage_type volatile&) BOOST_NOEXCEPT
0127     {
0128     }
0129 };
0130 
0131 template< typename Base, std::size_t Size, bool Interprocess >
0132 struct wait_operations< Base, Size, true, Interprocess > :
0133     public wait_operations_generic< Base, Interprocess >
0134 {
0135 };
0136 
0137 } // namespace detail
0138 } // namespace atomics
0139 } // namespace boost
0140 
0141 #include <boost/atomic/detail/footer.hpp>
0142 
0143 #endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_