| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // WorkerThread: |
| // Asychronous tasks/threads for ANGLE, similar to a TaskRunner in Chromium. |
| // Can be implemented as different targets, depending on platform. |
| // |
| |
| #ifndef COMMON_WORKER_THREAD_H_ |
| #define COMMON_WORKER_THREAD_H_ |
| |
| #include <array> |
| #include <condition_variable> |
| #include <memory> |
| #include <mutex> |
| #include <vector> |
| |
| #include "common/debug.h" |
| #include "platform/PlatformMethods.h" |
| |
| namespace angle |
| { |
| |
| class WorkerThreadPool; |
| |
| // A callback function with no return value and no arguments. |
| class Closure |
| { |
| public: |
| virtual ~Closure() = default; |
| virtual void operator()() = 0; |
| }; |
| |
| // An event that we can wait on, useful for joining worker threads. |
| class WaitableEvent : angle::NonCopyable |
| { |
| public: |
| WaitableEvent(); |
| virtual ~WaitableEvent(); |
| |
| // Waits indefinitely for the event to be signaled. |
| virtual void wait() = 0; |
| |
| // Peeks whether the event is ready. If ready, wait() will not block. |
| virtual bool isReady() = 0; |
| |
| template <class T> |
| // Waits on multiple events. T should be some container of std::shared_ptr<WaitableEvent>. |
| static void WaitMany(T *waitables) |
| { |
| for (auto &waitable : *waitables) |
| { |
| waitable->wait(); |
| } |
| } |
| |
| template <class T> |
| // Checks if all events are ready. T should be some container of std::shared_ptr<WaitableEvent>. |
| static bool AllReady(T *waitables) |
| { |
| for (auto &waitable : *waitables) |
| { |
| if (!waitable->isReady()) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| }; |
| |
| // A waitable event that is always ready. |
| class WaitableEventDone final : public WaitableEvent |
| { |
| public: |
| void wait() override; |
| bool isReady() override; |
| }; |
| |
| // A waitable event that can be completed asynchronously |
| class AsyncWaitableEvent final : public WaitableEvent |
| { |
| public: |
| AsyncWaitableEvent() = default; |
| ~AsyncWaitableEvent() override = default; |
| |
| void wait() override; |
| bool isReady() override; |
| |
| void markAsReady(); |
| |
| private: |
| // To protect the concurrent accesses from both main thread and background |
| // threads to the member fields. |
| std::mutex mMutex; |
| |
| bool mIsReady = false; |
| std::condition_variable mCondition; |
| }; |
| |
| // Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so |
| // we avoid the costly spin up and spin down time. |
| class WorkerThreadPool : angle::NonCopyable |
| { |
| public: |
| WorkerThreadPool(); |
| virtual ~WorkerThreadPool(); |
| |
| // Creates a new thread pool. |
| // If numThreads is 0, the pool will choose the best number of threads to run. |
| // If numThreads is 1, the pool will be single-threaded. Tasks will run on the calling thread. |
| // Other numbers indicate how many threads the pool should spawn. |
| // Note that based on build options, this class may not actually run tasks in threads, or it may |
| // hook into the provided PlatformMethods::postWorkerTask, in which case numThreads is ignored. |
| static std::shared_ptr<WorkerThreadPool> Create(size_t numThreads, PlatformMethods *platform); |
| |
| // Returns an event to wait on for the task to finish. If the pool fails to create the task, |
| // returns null. This function is thread-safe. |
| virtual std::shared_ptr<WaitableEvent> postWorkerTask(const std::shared_ptr<Closure> &task) = 0; |
| |
| virtual bool isAsync() = 0; |
| |
| private: |
| }; |
| |
| } // namespace angle |
| |
| #endif // COMMON_WORKER_THREAD_H_ |