| // |
| // 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(); |
| void markAsAborted(); |
| |
| private: |
| // To protect the concurrent accesses from both main thread and background |
| // threads to the member fields. |
| std::mutex mMutex; |
| |
| bool mIsReady = false; |
| bool mAborted = false; |
| std::condition_variable mCondition; |
| }; |
| |
| enum class ThreadPoolType |
| { |
| Asynchronous = 0, |
| Synchronous = 1, |
| }; |
| |
| // 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 <type> is Asynchronous, <numThreads> count of threads are spawned. If numThreads is 0, |
| // the pool chooses the count based on the number of concurrent threads supported by the |
| // platform. Note that based on build options, tasks may not actually run in an async thread. |
| // |
| // When angle_delegate_workers is enabled, like on Chromium, the pool hooks into the provided |
| // PlatformMethods::postWorkerTask and numThreads is ignored. |
| // |
| // If <type> is Synchronous, the pool has no additional threads and tasks are executed |
| // inline on the calling thread. |
| static std::shared_ptr<WorkerThreadPool> Create(ThreadPoolType type, |
| 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; |
| |
| virtual size_t getEnqueuedTaskCount() { return 0; } |
| |
| private: |
| }; |
| |
| } // namespace angle |
| |
| #endif // COMMON_WORKER_THREAD_H_ |