annotate DEPENDENCIES/generic/include/boost/interprocess/sync/spin/wait.hpp @ 16:2665513ce2d3

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