thread.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <chrono>
  6. #include <condition_variable>
  7. #include <cstddef>
  8. #include <mutex>
  9. #include <thread>
  10. #include "common/common_types.h"
  11. // Support for C++11's thread_local keyword was surprisingly spotty in compilers until very
  12. // recently. Fortunately, thread local variables have been well supported for compilers for a while,
  13. // but with semantics supporting only POD types, so we can use a few defines to get some amount of
  14. // backwards compat support.
  15. // WARNING: This only works correctly with POD types.
  16. #if defined(__clang__)
  17. #if !__has_feature(cxx_thread_local)
  18. #define thread_local __thread
  19. #endif
  20. #elif defined(__GNUC__)
  21. #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
  22. #define thread_local __thread
  23. #endif
  24. #elif defined(_MSC_VER)
  25. #if _MSC_VER < 1900
  26. #define thread_local __declspec(thread)
  27. #endif
  28. #endif
  29. namespace Common {
  30. int CurrentThreadId();
  31. void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
  32. void SetCurrentThreadAffinity(u32 mask);
  33. class Event {
  34. public:
  35. Event() : is_set(false) {}
  36. void Set() {
  37. std::lock_guard<std::mutex> lk(mutex);
  38. if (!is_set) {
  39. is_set = true;
  40. condvar.notify_one();
  41. }
  42. }
  43. void Wait() {
  44. std::unique_lock<std::mutex> lk(mutex);
  45. condvar.wait(lk, [&] { return is_set; });
  46. is_set = false;
  47. }
  48. template <class Clock, class Duration>
  49. bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
  50. std::unique_lock<std::mutex> lk(mutex);
  51. if (!condvar.wait_until(lk, time, [this] { return is_set; }))
  52. return false;
  53. is_set = false;
  54. return true;
  55. }
  56. void Reset() {
  57. std::unique_lock<std::mutex> lk(mutex);
  58. // no other action required, since wait loops on the predicate and any lingering signal will
  59. // get cleared on the first iteration
  60. is_set = false;
  61. }
  62. private:
  63. bool is_set;
  64. std::condition_variable condvar;
  65. std::mutex mutex;
  66. };
  67. class Barrier {
  68. public:
  69. explicit Barrier(size_t count_) : count(count_), waiting(0), generation(0) {}
  70. /// Blocks until all "count" threads have called Sync()
  71. void Sync() {
  72. std::unique_lock<std::mutex> lk(mutex);
  73. const size_t current_generation = generation;
  74. if (++waiting == count) {
  75. generation++;
  76. waiting = 0;
  77. condvar.notify_all();
  78. } else {
  79. condvar.wait(lk,
  80. [this, current_generation] { return current_generation != generation; });
  81. }
  82. }
  83. private:
  84. std::condition_variable condvar;
  85. std::mutex mutex;
  86. const size_t count;
  87. size_t waiting;
  88. size_t generation; // Incremented once each time the barrier is used
  89. };
  90. void SleepCurrentThread(int ms);
  91. void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
  92. // Use this function during a spin-wait to make the current thread
  93. // relax while another thread is working. This may be more efficient
  94. // than using events because event functions use kernel calls.
  95. inline void YieldCPU() {
  96. std::this_thread::yield();
  97. }
  98. void SetCurrentThreadName(const char* name);
  99. } // namespace Common