thread_group.hpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright 2015-2017 ARM Limited
  3. * SPDX-License-Identifier: Apache-2.0
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #ifndef SPIRV_CROSS_THREAD_GROUP_HPP
  18. #define SPIRV_CROSS_THREAD_GROUP_HPP
  19. #include <condition_variable>
  20. #include <mutex>
  21. #include <thread>
  22. namespace spirv_cross
  23. {
  24. template <typename T, unsigned Size>
  25. class ThreadGroup
  26. {
  27. public:
  28. ThreadGroup(T *impl)
  29. {
  30. for (unsigned i = 0; i < Size; i++)
  31. workers[i].start(&impl[i]);
  32. }
  33. void run()
  34. {
  35. for (auto &worker : workers)
  36. worker.run();
  37. }
  38. void wait()
  39. {
  40. for (auto &worker : workers)
  41. worker.wait();
  42. }
  43. private:
  44. struct Thread
  45. {
  46. enum State
  47. {
  48. Idle,
  49. Running,
  50. Dying
  51. };
  52. State state = Idle;
  53. void start(T *impl)
  54. {
  55. worker = std::thread([impl, this] {
  56. for (;;)
  57. {
  58. {
  59. std::unique_lock<std::mutex> l{ lock };
  60. cond.wait(l, [this] { return state != Idle; });
  61. if (state == Dying)
  62. break;
  63. }
  64. impl->main();
  65. std::lock_guard<std::mutex> l{ lock };
  66. state = Idle;
  67. cond.notify_one();
  68. }
  69. });
  70. }
  71. void wait()
  72. {
  73. std::unique_lock<std::mutex> l{ lock };
  74. cond.wait(l, [this] { return state == Idle; });
  75. }
  76. void run()
  77. {
  78. std::lock_guard<std::mutex> l{ lock };
  79. state = Running;
  80. cond.notify_one();
  81. }
  82. ~Thread()
  83. {
  84. if (worker.joinable())
  85. {
  86. {
  87. std::lock_guard<std::mutex> l{ lock };
  88. state = Dying;
  89. cond.notify_one();
  90. }
  91. worker.join();
  92. }
  93. }
  94. std::thread worker;
  95. std::condition_variable cond;
  96. std::mutex lock;
  97. };
  98. Thread workers[Size];
  99. };
  100. }
  101. #endif