1 // 2 // Copyright 2016 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // WorkerThread: 7 // Asychronous tasks/threads for ANGLE, similar to a TaskRunner in Chromium. 8 // Can be implemented as different targets, depending on platform. 9 // 10 11 #ifndef COMMON_WORKER_THREAD_H_ 12 #define COMMON_WORKER_THREAD_H_ 13 14 #include <array> 15 #include <condition_variable> 16 #include <memory> 17 #include <mutex> 18 #include <vector> 19 20 #include "common/debug.h" 21 #include "platform/PlatformMethods.h" 22 23 namespace angle 24 { 25 26 class WorkerThreadPool; 27 28 // A callback function with no return value and no arguments. 29 class Closure 30 { 31 public: 32 virtual ~Closure() = default; 33 virtual void operator()() = 0; 34 }; 35 36 // An event that we can wait on, useful for joining worker threads. 37 class WaitableEvent : angle::NonCopyable 38 { 39 public: 40 WaitableEvent(); 41 virtual ~WaitableEvent(); 42 43 // Waits indefinitely for the event to be signaled. 44 virtual void wait() = 0; 45 46 // Peeks whether the event is ready. If ready, wait() will not block. 47 virtual bool isReady() = 0; 48 49 template <class T> 50 // Waits on multiple events. T should be some container of std::shared_ptr<WaitableEvent>. WaitMany(T * waitables)51 static void WaitMany(T *waitables) 52 { 53 for (auto &waitable : *waitables) 54 { 55 waitable->wait(); 56 } 57 } 58 59 template <class T> 60 // Checks if all events are ready. T should be some container of std::shared_ptr<WaitableEvent>. AllReady(T * waitables)61 static bool AllReady(T *waitables) 62 { 63 for (auto &waitable : *waitables) 64 { 65 if (!waitable->isReady()) 66 { 67 return false; 68 } 69 } 70 return true; 71 } 72 }; 73 74 // A waitable event that is always ready. 75 class WaitableEventDone final : public WaitableEvent 76 { 77 public: 78 void wait() override; 79 bool isReady() override; 80 }; 81 82 // A waitable event that can be completed asynchronously 83 class AsyncWaitableEvent final : public WaitableEvent 84 { 85 public: 86 AsyncWaitableEvent() = default; 87 ~AsyncWaitableEvent() override = default; 88 89 void wait() override; 90 bool isReady() override; 91 92 void markAsReady(); 93 94 private: 95 // To protect the concurrent accesses from both main thread and background 96 // threads to the member fields. 97 std::mutex mMutex; 98 99 bool mIsReady = false; 100 std::condition_variable mCondition; 101 }; 102 103 // Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so 104 // we avoid the costly spin up and spin down time. 105 class WorkerThreadPool : angle::NonCopyable 106 { 107 public: 108 WorkerThreadPool(); 109 virtual ~WorkerThreadPool(); 110 111 // Creates a new thread pool. 112 // If numThreads is 0, the pool will choose the best number of threads to run. 113 // If numThreads is 1, the pool will be single-threaded. Tasks will run on the calling thread. 114 // Other numbers indicate how many threads the pool should spawn. 115 // Note that based on build options, this class may not actually run tasks in threads, or it may 116 // hook into the provided PlatformMethods::postWorkerTask, in which case numThreads is ignored. 117 static std::shared_ptr<WorkerThreadPool> Create(size_t numThreads, PlatformMethods *platform); 118 119 // Returns an event to wait on for the task to finish. If the pool fails to create the task, 120 // returns null. This function is thread-safe. 121 virtual std::shared_ptr<WaitableEvent> postWorkerTask(const std::shared_ptr<Closure> &task) = 0; 122 123 virtual bool isAsync() = 0; 124 125 private: 126 }; 127 128 } // namespace angle 129 130 #endif // COMMON_WORKER_THREAD_H_ 131