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