thread.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2013 Dolphin Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. #ifndef _THREAD_H_
  5. #define _THREAD_H_
  6. #include "common/std_condition_variable.h"
  7. #include "common/std_mutex.h"
  8. #include "common/std_thread.h"
  9. // Don't include common.h here as it will break LogManager
  10. #include "common/common_types.h"
  11. #include <stdio.h>
  12. #include <string.h>
  13. // This may not be defined outside _WIN32
  14. #ifndef _WIN32
  15. #ifndef INFINITE
  16. #define INFINITE 0xffffffff
  17. #endif
  18. //for gettimeofday and struct time(spec|val)
  19. #include <time.h>
  20. #include <sys/time.h>
  21. #endif
  22. namespace Common
  23. {
  24. int CurrentThreadId();
  25. void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
  26. void SetCurrentThreadAffinity(u32 mask);
  27. class Event
  28. {
  29. public:
  30. Event()
  31. : is_set(false)
  32. {};
  33. void Set()
  34. {
  35. std::lock_guard<std::mutex> lk(m_mutex);
  36. if (!is_set)
  37. {
  38. is_set = true;
  39. m_condvar.notify_one();
  40. }
  41. }
  42. void Wait()
  43. {
  44. std::unique_lock<std::mutex> lk(m_mutex);
  45. m_condvar.wait(lk, IsSet(this));
  46. is_set = false;
  47. }
  48. void Reset()
  49. {
  50. std::unique_lock<std::mutex> lk(m_mutex);
  51. // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
  52. is_set = false;
  53. }
  54. private:
  55. class IsSet
  56. {
  57. public:
  58. IsSet(const Event* ev)
  59. : m_event(ev)
  60. {}
  61. bool operator()()
  62. {
  63. return m_event->is_set;
  64. }
  65. private:
  66. const Event* const m_event;
  67. };
  68. volatile bool is_set;
  69. std::condition_variable m_condvar;
  70. std::mutex m_mutex;
  71. };
  72. // TODO: doesn't work on windows with (count > 2)
  73. class Barrier
  74. {
  75. public:
  76. Barrier(size_t count)
  77. : m_count(count), m_waiting(0)
  78. {}
  79. // block until "count" threads call Sync()
  80. bool Sync()
  81. {
  82. std::unique_lock<std::mutex> lk(m_mutex);
  83. // TODO: broken when next round of Sync()s
  84. // is entered before all waiting threads return from the notify_all
  85. if (m_count == ++m_waiting)
  86. {
  87. m_waiting = 0;
  88. m_condvar.notify_all();
  89. return true;
  90. }
  91. else
  92. {
  93. m_condvar.wait(lk, IsDoneWating(this));
  94. return false;
  95. }
  96. }
  97. private:
  98. class IsDoneWating
  99. {
  100. public:
  101. IsDoneWating(const Barrier* bar)
  102. : m_bar(bar)
  103. {}
  104. bool operator()()
  105. {
  106. return (0 == m_bar->m_waiting);
  107. }
  108. private:
  109. const Barrier* const m_bar;
  110. };
  111. std::condition_variable m_condvar;
  112. std::mutex m_mutex;
  113. const size_t m_count;
  114. volatile size_t m_waiting;
  115. };
  116. void SleepCurrentThread(int ms);
  117. void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
  118. // Use this function during a spin-wait to make the current thread
  119. // relax while another thread is working. This may be more efficient
  120. // than using events because event functions use kernel calls.
  121. inline void YieldCPU()
  122. {
  123. std::this_thread::yield();
  124. }
  125. void SetCurrentThreadName(const char *name);
  126. } // namespace Common
  127. #endif // _THREAD_H_