yield_k.hpp 2.9 KB

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