/* * Copyright 2015-2017 ARM Limited * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SPIRV_CROSS_THREAD_GROUP_HPP #define SPIRV_CROSS_THREAD_GROUP_HPP #include #include #include namespace spirv_cross { template class ThreadGroup { public: ThreadGroup(T *impl) { for (unsigned i = 0; i < Size; i++) workers[i].start(&impl[i]); } void run() { for (auto &worker : workers) worker.run(); } void wait() { for (auto &worker : workers) worker.wait(); } private: struct Thread { enum State { Idle, Running, Dying }; State state = Idle; void start(T *impl) { worker = std::thread([impl, this] { for (;;) { { std::unique_lock l{ lock }; cond.wait(l, [this] { return state != Idle; }); if (state == Dying) break; } impl->main(); std::lock_guard l{ lock }; state = Idle; cond.notify_one(); } }); } void wait() { std::unique_lock l{ lock }; cond.wait(l, [this] { return state == Idle; }); } void run() { std::lock_guard l{ lock }; state = Running; cond.notify_one(); } ~Thread() { if (worker.joinable()) { { std::lock_guard l{ lock }; state = Dying; cond.notify_one(); } worker.join(); } } std::thread worker; std::condition_variable cond; std::mutex lock; }; Thread workers[Size]; }; } #endif