File indexing completed on 2025-01-18 09:38:32
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
0037 #if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) )
0038
0039 extern "C" void _mm_pause();
0040 #pragma intrinsic( _mm_pause )
0041
0042 #define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
0043
0044 #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC)
0045
0046 #define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
0047
0048 #endif
0049
0050 namespace boost{
0051 namespace interprocess{
0052 namespace ipcdetail {
0053
0054 template<int Dummy = 0>
0055 class num_core_holder
0056 {
0057 public:
0058 static unsigned int get()
0059 {
0060 if(!num_cores){
0061 return ipcdetail::get_num_cores();
0062 }
0063 else{
0064 return num_cores;
0065 }
0066 }
0067
0068 private:
0069 static unsigned int num_cores;
0070 };
0071
0072 template<int Dummy>
0073 unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
0074
0075 }
0076
0077 class spin_wait
0078 {
0079 public:
0080
0081 static const unsigned int nop_pause_limit = 32u;
0082 spin_wait()
0083 : m_count_start(), m_ul_yield_only_counts(), m_k()
0084 {}
0085
0086 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
0087 ~spin_wait()
0088 {
0089 if(m_k){
0090 std::cout << "final m_k: " << m_k
0091 << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
0092 }
0093 }
0094 #endif
0095
0096 unsigned int count() const
0097 { return m_k; }
0098
0099 void yield()
0100 {
0101
0102 if( !m_k){
0103 this->init_limits();
0104 }
0105
0106 if( m_k < (nop_pause_limit >> 2) ){
0107
0108 }
0109
0110 #if defined(BOOST_INTERPROCESS_SMT_PAUSE)
0111 else if( m_k < nop_pause_limit ){
0112 BOOST_INTERPROCESS_SMT_PAUSE
0113 }
0114 #endif
0115
0116 else{
0117
0118 if(m_k == nop_pause_limit){
0119 this->init_tick_info();
0120 }
0121 else if( this->yield_or_sleep() ){
0122 ipcdetail::thread_yield();
0123 }
0124 else{
0125 ipcdetail::thread_sleep_tick();
0126 }
0127 }
0128 ++m_k;
0129 }
0130
0131 void reset()
0132 {
0133 m_k = 0u;
0134 }
0135
0136 private:
0137
0138 void init_limits()
0139 {
0140 unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
0141 m_k = num_cores > 1u ? 0u : nop_pause_limit;
0142 }
0143
0144 void init_tick_info()
0145 {
0146 m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
0147 m_count_start = ipcdetail::get_current_system_highres_count();
0148 }
0149
0150
0151 bool yield_or_sleep()
0152 {
0153 if(!m_ul_yield_only_counts){
0154 return (m_k & 1u) != 0;
0155 }
0156 else{
0157 const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
0158 const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
0159 if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){
0160 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
0161 std::cout << "elapsed!\n"
0162 << " m_ul_yield_only_counts: " << m_ul_yield_only_counts
0163 << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
0164 << " m_k: " << m_k << " elapsed counts: ";
0165 ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
0166 #endif
0167
0168 m_ul_yield_only_counts = 0ul;
0169 return false;
0170 }
0171 }
0172 return true;
0173 }
0174
0175 ipcdetail::OS_highres_count_t m_count_start;
0176 unsigned long m_ul_yield_only_counts;
0177 unsigned int m_k;
0178 };
0179
0180 }
0181 }
0182
0183 #include <boost/interprocess/detail/config_end.hpp>
0184
0185 #endif