1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_ |
6 | #define FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_ |
7 | |
8 | #include <condition_variable> |
9 | #include <mutex> |
10 | |
11 | #include "flutter/fml/macros.h" |
12 | #include "flutter/fml/memory/ref_counted.h" |
13 | #include "flutter/fml/message_loop_task_queues.h" |
14 | #include "flutter/fml/shared_thread_merger.h" |
15 | |
16 | namespace fml { |
17 | |
18 | class MessageLoopImpl; |
19 | |
20 | enum class RasterThreadStatus { |
21 | kRemainsMerged, |
22 | kRemainsUnmerged, |
23 | kUnmergedNow |
24 | }; |
25 | |
26 | /// This class is a client and proxy between the rasterizer and |
27 | /// |SharedThreadMerger|. The multiple |RasterThreadMerger| instances with same |
28 | /// owner_queue_id and same subsumed_queue_id share the same |
29 | /// |SharedThreadMerger| instance. Whether they share the same inner instance is |
30 | /// determined by |RasterThreadMerger::CreateOrShareThreadMerger| method. |
31 | class RasterThreadMerger |
32 | : public fml::RefCountedThreadSafe<RasterThreadMerger> { |
33 | public: |
34 | // Merges the raster thread into platform thread for the duration of |
35 | // the lease term. Lease is managed by the caller by either calling |
36 | // |ExtendLeaseTo| or |DecrementLease|. |
37 | // When the caller merges with a lease term of say 2. The threads |
38 | // are going to remain merged until 2 invocations of |DecreaseLease|, |
39 | // unless an |ExtendLeaseTo| gets called. |
40 | // |
41 | // If the task queues are the same, we consider them statically merged. |
42 | // When task queues are statically merged this method becomes no-op. |
43 | void MergeWithLease(size_t lease_term); |
44 | |
45 | // Gets the shared merger from current merger object |
46 | const fml::RefPtr<SharedThreadMerger>& GetSharedRasterThreadMerger() const; |
47 | |
48 | /// Creates a new merger from parent, share the inside shared_merger member |
49 | /// when the platform_queue_id and raster_queue_id are same, otherwise create |
50 | /// a new shared_merger instance |
51 | static fml::RefPtr<fml::RasterThreadMerger> CreateOrShareThreadMerger( |
52 | const fml::RefPtr<fml::RasterThreadMerger>& parent_merger, |
53 | TaskQueueId platform_id, |
54 | TaskQueueId raster_id); |
55 | |
56 | // Un-merges the threads now if current caller is the last merged caller, |
57 | // and it resets the lease term to 0, otherwise it will remove |
58 | // the caller record and return. The multiple caller records were recorded |
59 | // after |MergeWithLease| or |ExtendLeaseTo| method. |
60 | // |
61 | // Must be executed on the raster task runner. |
62 | // |
63 | // If the task queues are the same, we consider them statically merged. |
64 | // When task queues are statically merged, we never unmerge them and |
65 | // this method becomes no-op. |
66 | void UnMergeNowIfLastOne(); |
67 | |
68 | // If the task queues are the same, we consider them statically merged. |
69 | // When task queues are statically merged this method becomes no-op. |
70 | void ExtendLeaseTo(size_t lease_term); |
71 | |
72 | // Returns |RasterThreadStatus::kUnmergedNow| if this call resulted in |
73 | // splitting the raster and platform threads. Reduces the lease term by 1. |
74 | // |
75 | // If the task queues are the same, we consider them statically merged. |
76 | // When task queues are statically merged this method becomes no-op. |
77 | RasterThreadStatus DecrementLease(); |
78 | |
79 | // The method is locked by current instance, and asks the shared instance of |
80 | // SharedThreadMerger and the merging state is determined by the |
81 | // lease_term_ counter. |
82 | bool IsMerged(); |
83 | |
84 | // Waits until the threads are merged. |
85 | // |
86 | // Must run on the platform task runner. |
87 | void WaitUntilMerged(); |
88 | |
89 | // Returns true if the current thread owns rasterizing. |
90 | // When the threads are merged, platform thread owns rasterizing. |
91 | // When un-merged, raster thread owns rasterizing. |
92 | bool IsOnRasterizingThread(); |
93 | |
94 | // Returns true if the current thread is the platform thread. |
95 | bool IsOnPlatformThread() const; |
96 | |
97 | // Enables the thread merger. |
98 | void Enable(); |
99 | |
100 | // Disables the thread merger. Once disabled, any call to |
101 | // |MergeWithLease| or |UnMergeNowIfLastOne| results in a noop. |
102 | void Disable(); |
103 | |
104 | // Whether the thread merger is enabled. By default, the thread merger is |
105 | // enabled. If false, calls to |MergeWithLease| or |UnMergeNowIfLastOne| |
106 | // or |ExtendLeaseTo| or |DecrementLease| results in a noop. |
107 | bool IsEnabled(); |
108 | |
109 | // Registers a callback that can be used to clean up global state right after |
110 | // the thread configuration has changed. |
111 | // |
112 | // For example, it can be used to clear the GL context so it can be used in |
113 | // the next task from a different thread. |
114 | void SetMergeUnmergeCallback(const fml::closure& callback); |
115 | |
116 | private: |
117 | fml::TaskQueueId platform_queue_id_; |
118 | fml::TaskQueueId gpu_queue_id_; |
119 | |
120 | RasterThreadMerger(fml::TaskQueueId platform_queue_id, |
121 | fml::TaskQueueId gpu_queue_id); |
122 | RasterThreadMerger(fml::RefPtr<fml::SharedThreadMerger> shared_merger, |
123 | fml::TaskQueueId platform_queue_id, |
124 | fml::TaskQueueId gpu_queue_id); |
125 | |
126 | const fml::RefPtr<fml::SharedThreadMerger> shared_merger_; |
127 | std::condition_variable merged_condition_; |
128 | std::mutex mutex_; |
129 | fml::closure merge_unmerge_callback_; |
130 | |
131 | bool IsMergedUnSafe() const; |
132 | |
133 | bool IsEnabledUnSafe() const; |
134 | |
135 | // The platform_queue_id and gpu_queue_id are exactly the same. |
136 | // We consider the threads are always merged and cannot be unmerged. |
137 | bool TaskQueuesAreSame() const; |
138 | |
139 | FML_FRIEND_REF_COUNTED_THREAD_SAFE(RasterThreadMerger); |
140 | FML_FRIEND_MAKE_REF_COUNTED(RasterThreadMerger); |
141 | FML_DISALLOW_COPY_AND_ASSIGN(RasterThreadMerger); |
142 | }; |
143 | |
144 | } // namespace fml |
145 | |
146 | #endif // FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_ |
147 | |