annotate DEPENDENCIES/generic/include/boost/interprocess/sync/spin/wait.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //////////////////////////////////////////////////////////////////////////////
Chris@16 2 //
Chris@16 3 // (C) Copyright Peter Dimov 2008.
Chris@16 4 // (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost
Chris@16 5 // Software License, Version 1.0. (See accompanying file
Chris@16 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 //
Chris@16 8 // See http://www.boost.org/libs/interprocess for documentation.
Chris@16 9 //
Chris@16 10 //////////////////////////////////////////////////////////////////////////////
Chris@16 11
Chris@16 12 //Parts of this file come from boost/smart_ptr/detail/yield_k.hpp
Chris@16 13 //Many thanks to Peter Dimov.
Chris@16 14
Chris@16 15 #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
Chris@16 16 #define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
Chris@16 17
Chris@101 18 #ifndef BOOST_CONFIG_HPP
Chris@101 19 # include <boost/config.hpp>
Chris@101 20 #endif
Chris@101 21 #
Chris@101 22 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@16 23 # pragma once
Chris@16 24 #endif
Chris@16 25
Chris@16 26 #include <boost/interprocess/detail/config_begin.hpp>
Chris@16 27 #include <boost/interprocess/detail/workaround.hpp>
Chris@16 28 #include <boost/interprocess/detail/os_thread_functions.hpp>
Chris@16 29
Chris@16 30 //#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
Chris@16 31 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
Chris@16 32 #include <iostream>
Chris@16 33 #endif
Chris@16 34
Chris@16 35 // BOOST_INTERPROCESS_SMT_PAUSE
Chris@16 36
Chris@101 37 #if defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) )
Chris@16 38
Chris@16 39 extern "C" void _mm_pause();
Chris@16 40 #pragma intrinsic( _mm_pause )
Chris@16 41
Chris@16 42 #define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
Chris@16 43
Chris@101 44 #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) && !defined(_CRAYC)
Chris@16 45
Chris@16 46 #define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
Chris@16 47
Chris@16 48 #endif
Chris@16 49
Chris@16 50 namespace boost{
Chris@16 51 namespace interprocess{
Chris@16 52 namespace ipcdetail {
Chris@16 53
Chris@16 54 template<int Dummy = 0>
Chris@16 55 class num_core_holder
Chris@16 56 {
Chris@16 57 public:
Chris@16 58 static unsigned int get()
Chris@16 59 {
Chris@16 60 if(!num_cores){
Chris@16 61 return ipcdetail::get_num_cores();
Chris@16 62 }
Chris@16 63 else{
Chris@16 64 return num_cores;
Chris@16 65 }
Chris@16 66 }
Chris@16 67
Chris@16 68 private:
Chris@16 69 static unsigned int num_cores;
Chris@16 70 };
Chris@16 71
Chris@16 72 template<int Dummy>
Chris@16 73 unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
Chris@16 74
Chris@16 75 } //namespace ipcdetail {
Chris@16 76
Chris@16 77 class spin_wait
Chris@16 78 {
Chris@16 79 public:
Chris@16 80
Chris@16 81 static const unsigned int nop_pause_limit = 32u;
Chris@16 82 spin_wait()
Chris@16 83 : m_count_start(), m_ul_yield_only_counts(), m_k()
Chris@16 84 {}
Chris@16 85
Chris@16 86 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
Chris@16 87 ~spin_wait()
Chris@16 88 {
Chris@16 89 if(m_k){
Chris@16 90 std::cout << "final m_k: " << m_k
Chris@16 91 << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
Chris@16 92 }
Chris@16 93 }
Chris@16 94 #endif
Chris@16 95
Chris@16 96 unsigned int count() const
Chris@16 97 { return m_k; }
Chris@16 98
Chris@16 99 void yield()
Chris@16 100 {
Chris@16 101 //Lazy initialization of limits
Chris@16 102 if( !m_k){
Chris@16 103 this->init_limits();
Chris@16 104 }
Chris@16 105 //Nop tries
Chris@16 106 if( m_k < (nop_pause_limit >> 2) ){
Chris@16 107
Chris@16 108 }
Chris@16 109 //Pause tries if the processor supports it
Chris@16 110 #if defined(BOOST_INTERPROCESS_SMT_PAUSE)
Chris@16 111 else if( m_k < nop_pause_limit ){
Chris@16 112 BOOST_INTERPROCESS_SMT_PAUSE
Chris@16 113 }
Chris@16 114 #endif
Chris@16 115 //Yield/Sleep strategy
Chris@16 116 else{
Chris@16 117 //Lazy initialization of tick information
Chris@16 118 if(m_k == nop_pause_limit){
Chris@16 119 this->init_tick_info();
Chris@16 120 }
Chris@16 121 else if( this->yield_or_sleep() ){
Chris@16 122 ipcdetail::thread_yield();
Chris@16 123 }
Chris@16 124 else{
Chris@16 125 ipcdetail::thread_sleep_tick();
Chris@16 126 }
Chris@16 127 }
Chris@16 128 ++m_k;
Chris@16 129 }
Chris@16 130
Chris@16 131 void reset()
Chris@16 132 {
Chris@16 133 m_k = 0u;
Chris@16 134 }
Chris@16 135
Chris@16 136 private:
Chris@16 137
Chris@16 138 void init_limits()
Chris@16 139 {
Chris@16 140 unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
Chris@16 141 m_k = num_cores > 1u ? 0u : nop_pause_limit;
Chris@16 142 }
Chris@16 143
Chris@16 144 void init_tick_info()
Chris@16 145 {
Chris@16 146 m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
Chris@16 147 m_count_start = ipcdetail::get_current_system_highres_count();
Chris@16 148 }
Chris@16 149
Chris@16 150 //Returns true if yield must be called, false is sleep must be called
Chris@16 151 bool yield_or_sleep()
Chris@16 152 {
Chris@16 153 if(!m_ul_yield_only_counts){ //If yield-only limit was reached then yield one in every two tries
Chris@16 154 return (m_k & 1u) != 0;
Chris@16 155 }
Chris@16 156 else{ //Try to see if we've reched yield-only time limit
Chris@16 157 const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
Chris@16 158 const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
Chris@16 159 if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){
Chris@16 160 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
Chris@16 161 std::cout << "elapsed!\n"
Chris@16 162 << " m_ul_yield_only_counts: " << m_ul_yield_only_counts
Chris@16 163 << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
Chris@16 164 << " m_k: " << m_k << " elapsed counts: ";
Chris@16 165 ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
Chris@16 166 #endif
Chris@16 167 //Yield-only time reached, now it's time to sleep
Chris@16 168 m_ul_yield_only_counts = 0ul;
Chris@16 169 return false;
Chris@16 170 }
Chris@16 171 }
Chris@16 172 return true; //Otherwise yield
Chris@16 173 }
Chris@16 174
Chris@16 175 ipcdetail::OS_highres_count_t m_count_start;
Chris@16 176 unsigned long m_ul_yield_only_counts;
Chris@16 177 unsigned int m_k;
Chris@16 178 };
Chris@16 179
Chris@16 180 } // namespace interprocess
Chris@16 181 } // namespace boost
Chris@16 182
Chris@16 183 #include <boost/interprocess/detail/config_end.hpp>
Chris@16 184
Chris@16 185 #endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED