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 18 #ifndef SPIRV_CROSS_THREAD_GROUP_HPP 19 #define SPIRV_CROSS_THREAD_GROUP_HPP 20 21 #include <condition_variable> 22 #include <mutex> 23 #include <thread> 24 25 namespace spirv_cross 26 { 27 template <typename T, unsigned Size> 28 class ThreadGroup 29 { 30 public: ThreadGroup(T * impl)31 ThreadGroup(T *impl) 32 { 33 for (unsigned i = 0; i < Size; i++) 34 workers[i].start(&impl[i]); 35 } 36 run()37 void run() 38 { 39 for (auto &worker : workers) 40 worker.run(); 41 } 42 wait()43 void wait() 44 { 45 for (auto &worker : workers) 46 worker.wait(); 47 } 48 49 private: 50 struct Thread 51 { 52 enum State 53 { 54 Idle, 55 Running, 56 Dying 57 }; 58 State state = Idle; 59 startspirv_cross::ThreadGroup::Thread60 void start(T *impl) 61 { 62 worker = std::thread([impl, this] { 63 for (;;) 64 { 65 { 66 std::unique_lock<std::mutex> l{ lock }; 67 cond.wait(l, [this] { return state != Idle; }); 68 if (state == Dying) 69 break; 70 } 71 72 impl->main(); 73 74 std::lock_guard<std::mutex> l{ lock }; 75 state = Idle; 76 cond.notify_one(); 77 } 78 }); 79 } 80 waitspirv_cross::ThreadGroup::Thread81 void wait() 82 { 83 std::unique_lock<std::mutex> l{ lock }; 84 cond.wait(l, [this] { return state == Idle; }); 85 } 86 runspirv_cross::ThreadGroup::Thread87 void run() 88 { 89 std::lock_guard<std::mutex> l{ lock }; 90 state = Running; 91 cond.notify_one(); 92 } 93 ~Threadspirv_cross::ThreadGroup::Thread94 ~Thread() 95 { 96 if (worker.joinable()) 97 { 98 { 99 std::lock_guard<std::mutex> l{ lock }; 100 state = Dying; 101 cond.notify_one(); 102 } 103 worker.join(); 104 } 105 } 106 std::thread worker; 107 std::condition_variable cond; 108 std::mutex lock; 109 }; 110 Thread workers[Size]; 111 }; 112 } 113 114 #endif 115