yield_k.hpp 3.3 KB

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