File indexing completed on 2025-12-16 09:53:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
0016 #define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
0017
0018 #ifndef BOOST_CONFIG_HPP
0019 # include <boost/config.hpp>
0020 #endif
0021 #
0022 #if defined(BOOST_HAS_PRAGMA_ONCE)
0023 # pragma once
0024 #endif
0025
0026 #include <boost/interprocess/detail/config_begin.hpp>
0027 #include <boost/interprocess/detail/workaround.hpp>
0028 #include <boost/interprocess/detail/os_thread_functions.hpp>
0029
0030
0031 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
0032 #include <iostream>
0033 #endif
0034
0035
0036 #if defined(_MSC_VER)
0037 #if defined(_M_AMD64) || defined(_M_IX86) || defined(_M_X64)
0038 extern "C" void _mm_pause(void);
0039 #if defined(BOOST_MSVC)
0040 #pragma intrinsic(_mm_pause)
0041 #endif
0042 #elif defined(_M_ARM64) || defined(_M_ARM)
0043 extern "C" void __yield(void);
0044 #if defined(BOOST_MSVC)
0045 #pragma intrinsic(__yield)
0046 #endif
0047 #endif
0048 #endif
0049
0050
0051
0052 #if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) )
0053
0054 #define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
0055
0056 #elif defined(_MSC_VER) && ( defined(_M_ARM64) || defined(_M_ARM) )
0057
0058 #define BOOST_INTERPROCESS_SMT_PAUSE __yield();
0059
0060 #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC)
0061
0062 #define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__("rep; nop" : : : "memory");
0063
0064 #elif defined(__GNUC__) && ((defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__) || defined(__aarch64__))
0065
0066 #define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__("yield;" : : : "memory");
0067
0068 #endif
0069
0070
0071 namespace boost{
0072 namespace interprocess{
0073 namespace ipcdetail {
0074
0075 template<int Dummy = 0>
0076 class num_core_holder
0077 {
0078 public:
0079 static unsigned int get()
0080 {
0081 if(!num_cores){
0082 return ipcdetail::get_num_cores();
0083 }
0084 else{
0085 return num_cores;
0086 }
0087 }
0088
0089 private:
0090 static unsigned int num_cores;
0091 };
0092
0093 template<int Dummy>
0094 unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
0095
0096 }
0097
0098 class spin_wait
0099 {
0100 public:
0101
0102 static const unsigned int nop_pause_limit = 32u;
0103 spin_wait()
0104 : m_count_start(), m_ul_yield_only_counts(), m_k()
0105 {}
0106
0107 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
0108 ~spin_wait()
0109 {
0110 if(m_k){
0111 std::cout << "final m_k: " << m_k
0112 << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
0113 }
0114 }
0115 #endif
0116
0117 unsigned int count() const
0118 { return m_k; }
0119
0120 void yield()
0121 {
0122
0123 if( !m_k){
0124 this->init_limits();
0125 }
0126
0127 if( m_k < (nop_pause_limit >> 2) ){
0128
0129 }
0130
0131 #if defined(BOOST_INTERPROCESS_SMT_PAUSE)
0132 else if( m_k < nop_pause_limit ){
0133 BOOST_INTERPROCESS_SMT_PAUSE
0134 }
0135 #endif
0136
0137 else{
0138
0139 if(m_k == nop_pause_limit){
0140 this->init_tick_info();
0141 }
0142 else if( this->yield_or_sleep() ){
0143 ipcdetail::thread_yield();
0144 }
0145 else{
0146 ipcdetail::thread_sleep_tick();
0147 }
0148 }
0149 ++m_k;
0150 }
0151
0152 void reset()
0153 {
0154 m_k = 0u;
0155 }
0156
0157 private:
0158
0159 void init_limits()
0160 {
0161 unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
0162 m_k = num_cores > 1u ? 0u : nop_pause_limit;
0163 }
0164
0165 void init_tick_info()
0166 {
0167 m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
0168 m_count_start = ipcdetail::get_current_system_highres_count();
0169 }
0170
0171
0172 bool yield_or_sleep()
0173 {
0174 if(!m_ul_yield_only_counts){
0175 return (m_k & 1u) != 0;
0176 }
0177 else{
0178 const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
0179 const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
0180 if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){
0181 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
0182 std::cout << "elapsed!\n"
0183 << " m_ul_yield_only_counts: " << m_ul_yield_only_counts
0184 << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
0185 << " m_k: " << m_k << " elapsed counts: ";
0186 ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
0187 #endif
0188
0189 m_ul_yield_only_counts = 0ul;
0190 return false;
0191 }
0192 }
0193 return true;
0194 }
0195
0196 ipcdetail::OS_highres_count_t m_count_start;
0197 unsigned long m_ul_yield_only_counts;
0198 unsigned int m_k;
0199 };
0200
0201 }
0202 }
0203
0204 #include <boost/interprocess/detail/config_end.hpp>
0205
0206 #endif