1 #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED 2 #define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED 3 4 // MS compatible compilers support #pragma once 5 6 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 7 # pragma once 8 #endif 9 10 // 11 // yield_k.hpp 12 // 13 // Copyright (c) 2008 Peter Dimov 14 // Copyright (c) Microsoft Corporation 2014 15 // 16 // void yield( unsigned k ); 17 // 18 // Typical use: 19 // 20 // for( unsigned k = 0; !try_lock(); ++k ) yield( k ); 21 // 22 // Distributed under the Boost Software License, Version 1.0. 23 // See accompanying file LICENSE_1_0.txt or copy at 24 // http://www.boost.org/LICENSE_1_0.txt 25 // 26 27 #include <boost/config.hpp> 28 #include <boost/predef.h> 29 30 #if BOOST_PLAT_WINDOWS_RUNTIME 31 #include <thread> 32 #endif 33 34 // BOOST_SMT_PAUSE 35 36 #if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__) 37 38 extern "C" void _mm_pause(); 39 40 #define BOOST_SMT_PAUSE _mm_pause(); 41 42 #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) 43 44 #define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); 45 46 #endif 47 48 // 49 50 #if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) 51 52 #if defined( BOOST_USE_WINDOWS_H ) 53 # include <windows.h> 54 #endif 55 56 namespace boost 57 { 58 59 namespace detail 60 { 61 62 #if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME 63 #if !BOOST_COMP_CLANG || !defined __MINGW32__ 64 extern "C" void __stdcall Sleep( unsigned long ms ); 65 #else 66 #include <_mingw.h> 67 #if !defined __MINGW64_VERSION_MAJOR 68 extern "C" void __stdcall Sleep( unsigned long ms ); 69 #else 70 extern "C" __declspec(dllimport) void __stdcall Sleep( unsigned long ms ); 71 #endif 72 #endif 73 #endif 74 yield(unsigned k)75inline void yield( unsigned k ) 76 { 77 if( k < 4 ) 78 { 79 } 80 #if defined( BOOST_SMT_PAUSE ) 81 else if( k < 16 ) 82 { 83 BOOST_SMT_PAUSE 84 } 85 #endif 86 #if !BOOST_PLAT_WINDOWS_RUNTIME 87 else if( k < 32 ) 88 { 89 Sleep( 0 ); 90 } 91 else 92 { 93 Sleep( 1 ); 94 } 95 #else 96 else 97 { 98 // Sleep isn't supported on the Windows Runtime. 99 std::this_thread::yield(); 100 } 101 #endif 102 } 103 104 } // namespace detail 105 106 } // namespace boost 107 108 #elif defined( BOOST_HAS_PTHREADS ) 109 110 #ifndef _AIX 111 #include <sched.h> 112 #else 113 // AIX's sched.h defines ::var which sometimes conflicts with Lambda's var 114 extern "C" int sched_yield(void); 115 #endif 116 117 #include <time.h> 118 119 namespace boost 120 { 121 122 namespace detail 123 { 124 yield(unsigned k)125inline void yield( unsigned k ) 126 { 127 if( k < 4 ) 128 { 129 } 130 #if defined( BOOST_SMT_PAUSE ) 131 else if( k < 16 ) 132 { 133 BOOST_SMT_PAUSE 134 } 135 #endif 136 else if( k < 32 || k & 1 ) 137 { 138 sched_yield(); 139 } 140 else 141 { 142 // g++ -Wextra warns on {} or {0} 143 struct timespec rqtp = { 0, 0 }; 144 145 // POSIX says that timespec has tv_sec and tv_nsec 146 // But it doesn't guarantee order or placement 147 148 rqtp.tv_sec = 0; 149 rqtp.tv_nsec = 1000; 150 151 nanosleep( &rqtp, 0 ); 152 } 153 } 154 155 } // namespace detail 156 157 } // namespace boost 158 159 #else 160 161 namespace boost 162 { 163 164 namespace detail 165 { 166 yield(unsigned)167inline void yield( unsigned ) 168 { 169 } 170 171 } // namespace detail 172 173 } // namespace boost 174 175 #endif 176 177 #endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED 178