thread.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
  2. // SPDX-FileCopyrightText: 2014 Citra Emulator Project
  3. // SPDX-License-Identifier: GPL-2.0-or-later
  4. #pragma once
  5. #include <atomic>
  6. #include <chrono>
  7. #include <condition_variable>
  8. #include <cstddef>
  9. #include <mutex>
  10. #include <thread>
  11. #include "common/common_types.h"
  12. #include "common/polyfill_thread.h"
  13. namespace Common {
  14. class Event {
  15. public:
  16. void Set() {
  17. std::scoped_lock lk{mutex};
  18. if (!is_set) {
  19. is_set = true;
  20. condvar.notify_one();
  21. }
  22. }
  23. void Wait() {
  24. std::unique_lock lk{mutex};
  25. condvar.wait(lk, [&] { return is_set.load(); });
  26. is_set = false;
  27. }
  28. bool WaitFor(const std::chrono::nanoseconds& time) {
  29. std::unique_lock lk{mutex};
  30. if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
  31. return false;
  32. is_set = false;
  33. return true;
  34. }
  35. template <class Clock, class Duration>
  36. bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
  37. std::unique_lock lk{mutex};
  38. if (!condvar.wait_until(lk, time, [this] { return is_set.load(); }))
  39. return false;
  40. is_set = false;
  41. return true;
  42. }
  43. void Reset() {
  44. std::unique_lock lk{mutex};
  45. // no other action required, since wait loops on the predicate and any lingering signal will
  46. // get cleared on the first iteration
  47. is_set = false;
  48. }
  49. [[nodiscard]] bool IsSet() {
  50. return is_set;
  51. }
  52. private:
  53. std::condition_variable condvar;
  54. std::mutex mutex;
  55. std::atomic_bool is_set{false};
  56. };
  57. class Barrier {
  58. public:
  59. explicit Barrier(std::size_t count_) : count(count_) {}
  60. /// Blocks until all "count" threads have called Sync()
  61. bool Sync(std::stop_token token = {}) {
  62. std::unique_lock lk{mutex};
  63. const std::size_t current_generation = generation;
  64. if (++waiting == count) {
  65. generation++;
  66. waiting = 0;
  67. condvar.notify_all();
  68. return true;
  69. } else {
  70. CondvarWait(condvar, lk, token,
  71. [this, current_generation] { return current_generation != generation; });
  72. return !token.stop_requested();
  73. }
  74. }
  75. private:
  76. std::condition_variable_any condvar;
  77. std::mutex mutex;
  78. std::size_t count;
  79. std::size_t waiting = 0;
  80. std::size_t generation = 0; // Incremented once each time the barrier is used
  81. };
  82. enum class ThreadPriority : u32 {
  83. Low = 0,
  84. Normal = 1,
  85. High = 2,
  86. VeryHigh = 3,
  87. Critical = 4,
  88. };
  89. void SetCurrentThreadPriority(ThreadPriority new_priority);
  90. void SetCurrentThreadName(const char* name);
  91. } // namespace Common