xref: /aosp_15_r20/external/angle/src/common/WorkerThread.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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