Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FlutterThreadSynchronizer.mm
Go to the documentation of this file.
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#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.h"
6
7#import <QuartzCore/QuartzCore.h>
8
9#include <mutex>
10#include <unordered_map>
11#include <vector>
12
13#import "flutter/fml/logging.h"
14#import "flutter/fml/synchronization/waitable_event.h"
15
16@interface FlutterThreadSynchronizer () {
17 dispatch_queue_t _mainQueue;
18 std::mutex _mutex;
20 std::unordered_map<int64_t, CGSize> _contentSizes;
21 std::vector<dispatch_block_t> _scheduledBlocks;
22
24
25 // Used to block [beginResize:].
26 std::condition_variable _condBlockBeginResize;
27}
28
29/**
30 * Returns true if all existing views have a non-zero size.
31 *
32 * If there are no views, still returns true.
33 */
34- (BOOL)allViewsHaveFrame;
35
36/**
37 * Returns true if there are any views that have a non-zero size.
38 *
39 * If there are no views, returns false.
40 */
41- (BOOL)someViewsHaveFrame;
42
43@end
44
45@implementation FlutterThreadSynchronizer
46
47- (instancetype)init {
48 return [self initWithMainQueue:dispatch_get_main_queue()];
49}
50
51- (instancetype)initWithMainQueue:(dispatch_queue_t)queue {
52 self = [super init];
53 if (self != nil) {
55 }
56 return self;
57}
58
60 for (auto const& [viewIdentifier, contentSize] : _contentSizes) {
61 if (CGSizeEqualToSize(contentSize, CGSizeZero)) {
62 return NO;
63 }
64 }
65 return YES;
66}
67
69 for (auto const& [viewIdentifier, contentSize] : _contentSizes) {
70 if (!CGSizeEqualToSize(contentSize, CGSizeZero)) {
71 return YES;
72 }
73 }
74 return NO;
75}
76
77- (void)drain {
78 dispatch_assert_queue(_mainQueue);
79
80 [CATransaction begin];
81 [CATransaction setDisableActions:YES];
82 for (dispatch_block_t block : _scheduledBlocks) {
83 block();
84 }
85 [CATransaction commit];
86 _scheduledBlocks.clear();
87}
88
90 std::unique_lock<std::mutex> lock(_mutex);
91 [self drain];
92
94 while (![self someViewsHaveFrame] && !_shuttingDown) {
95 _condBlockBeginResize.wait(lock);
96 [self drain];
97 }
98
100}
101
102- (void)beginResizeForView:(FlutterViewIdentifier)viewIdentifier
103 size:(CGSize)size
104 notify:(nonnull dispatch_block_t)notify {
105 dispatch_assert_queue(_mainQueue);
106 std::unique_lock<std::mutex> lock(_mutex);
107
108 if (![self allViewsHaveFrame] || _shuttingDown) {
109 // No blocking until framework produces at least one frame
110 notify();
111 return;
112 }
113
114 [self drain];
115
116 notify();
117
118 _contentSizes[viewIdentifier] = CGSizeMake(-1, -1);
119
121
122 while (true) {
123 if (_shuttingDown) {
124 break;
125 }
126 const CGSize& contentSize = _contentSizes[viewIdentifier];
127 if (CGSizeEqualToSize(contentSize, size) || CGSizeEqualToSize(contentSize, CGSizeZero)) {
128 break;
129 }
130 _condBlockBeginResize.wait(lock);
131 [self drain];
132 }
133
135}
136
137- (void)performCommitForView:(FlutterViewIdentifier)viewIdentifier
138 size:(CGSize)size
139 notify:(nonnull dispatch_block_t)notify {
140 dispatch_assert_queue_not(_mainQueue);
142 {
143 std::unique_lock<std::mutex> lock(_mutex);
144 if (_shuttingDown) {
145 // Engine is shutting down, main thread may be blocked by the engine
146 // waiting for raster thread to finish.
147 return;
148 }
150 _scheduledBlocks.push_back(^{
151 notify();
152 _contentSizes[viewIdentifier] = size;
153 e.Signal();
154 });
155 if (_beginResizeWaiting) {
156 _condBlockBeginResize.notify_all();
157 } else {
158 dispatch_async(_mainQueue, ^{
159 std::unique_lock<std::mutex> lock(_mutex);
160 [self drain];
161 });
162 }
163 }
164 event.Wait();
165}
166
167- (void)performOnPlatformThread:(nonnull dispatch_block_t)block {
168 std::unique_lock<std::mutex> lock(_mutex);
169 _scheduledBlocks.push_back(block);
170 if (_beginResizeWaiting) {
171 _condBlockBeginResize.notify_all();
172 } else {
173 dispatch_async(_mainQueue, ^{
174 std::unique_lock<std::mutex> lock(_mutex);
175 [self drain];
176 });
177 }
178}
179
180- (void)registerView:(FlutterViewIdentifier)viewIdentifier {
181 dispatch_assert_queue(_mainQueue);
182 std::unique_lock<std::mutex> lock(_mutex);
183 _contentSizes[viewIdentifier] = CGSizeZero;
184}
185
186- (void)deregisterView:(FlutterViewIdentifier)viewIdentifier {
187 dispatch_assert_queue(_mainQueue);
188 std::unique_lock<std::mutex> lock(_mutex);
189 _contentSizes.erase(viewIdentifier);
190}
191
192- (void)shutdown {
193 dispatch_assert_queue(_mainQueue);
194 std::unique_lock<std::mutex> lock(_mutex);
195 _shuttingDown = YES;
196 _condBlockBeginResize.notify_all();
197 [self drain];
198}
199
201 std::unique_lock<std::mutex> lock(_mutex);
202 return _beginResizeWaiting;
203}
204
205@end
VkQueue queue
Definition main.cc:55
FlKeyEvent * event
std::unordered_map< int64_t, CGSize > _contentSizes
std::vector< dispatch_block_t > _scheduledBlocks
std::condition_variable _condBlockBeginResize
int64_t FlutterViewIdentifier
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
int BOOL