// // 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 #include #include #include #include #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 // Waits on multiple events. T should be some container of std::shared_ptr. static void WaitMany(T *waitables) { for (auto &waitable : *waitables) { waitable->wait(); } } template // Checks if all events are ready. T should be some container of std::shared_ptr. 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 is Asynchronous, 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 is Synchronous, the pool has no additional threads and tasks are executed // inline on the calling thread. static std::shared_ptr 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 postWorkerTask(const std::shared_ptr &task) = 0; virtual bool isAsync() = 0; virtual size_t getEnqueuedTaskCount() { return 0; } private: }; } // namespace angle #endif // COMMON_WORKER_THREAD_H_