-
Notifications
You must be signed in to change notification settings - Fork 6k
Implemented FlutterEngineGroup and Spawn API. #22975
Changes from 1 commit
922f141
a3091d4
0923668
e5dd242
f3916b0
030b1f4
d56e93a
255e504
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #import <Foundation/Foundation.h> | ||
|
|
||
| #import "FlutterEngine.h" | ||
|
|
||
| NS_ASSUME_NONNULL_BEGIN | ||
|
|
||
| /** | ||
| * Represents a collection of FlutterEngines who share resources which allows | ||
| * them to be created with less time const and occupy less memory than just | ||
| * creating multiple FlutterEngines. | ||
|
gaaclarke marked this conversation as resolved.
|
||
| * | ||
| * @see http://flutter.dev/go/multiple-engines | ||
|
gaaclarke marked this conversation as resolved.
Outdated
|
||
| */ | ||
| @interface FlutterEngineGroup : NSObject | ||
| - (instancetype)init NS_UNAVAILABLE; | ||
| - (instancetype)initWithName:(NSString*)name | ||
| project:(nullable FlutterDartProject*)project NS_DESIGNATED_INITIALIZER; | ||
| - (FlutterEngine*)makeEngineWithEntrypoint:(nullable NSString*)entrypoint; | ||
| @end | ||
|
|
||
| NS_ASSUME_NONNULL_END | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,7 @@ | |
|
|
||
| NSString* const FlutterDefaultDartEntrypoint = nil; | ||
| NSString* const FlutterDefaultInitialRoute = nil; | ||
| NSString* const FlutterEngineWillDealloc = @"FlutterEngineWillDealloc"; | ||
| static constexpr int kNumProfilerSamplesPerSec = 5; | ||
|
|
||
| @interface FlutterEngineRegistrar : NSObject <FlutterPluginRegistrar> | ||
|
|
@@ -54,7 +55,7 @@ @interface FlutterEngine () <FlutterTextInputDelegate, FlutterBinaryMessenger> | |
|
|
||
| @implementation FlutterEngine { | ||
| fml::scoped_nsobject<FlutterDartProject> _dartProject; | ||
| flutter::ThreadHost _threadHost; | ||
| std::shared_ptr<flutter::ThreadHost> _threadHost; | ||
| std::unique_ptr<flutter::Shell> _shell; | ||
| NSString* _labelPrefix; | ||
| std::unique_ptr<fml::WeakPtrFactory<FlutterEngine>> _weakFactory; | ||
|
|
@@ -64,8 +65,8 @@ @implementation FlutterEngine { | |
|
|
||
| std::shared_ptr<flutter::FlutterPlatformViewsController> _platformViewsController; | ||
| flutter::IOSRenderingAPI _renderingApi; | ||
| std::unique_ptr<flutter::ProfilerMetricsIOS> _profiler_metrics; | ||
| std::unique_ptr<flutter::SamplingProfiler> _profiler; | ||
| std::shared_ptr<flutter::ProfilerMetricsIOS> _profiler_metrics; | ||
| std::shared_ptr<flutter::SamplingProfiler> _profiler; | ||
|
|
||
| // Channels | ||
| fml::scoped_nsobject<FlutterPlatformPlugin> _platformPlugin; | ||
|
|
@@ -181,6 +182,10 @@ - (void)dealloc { | |
| } | ||
| }]; | ||
|
|
||
| [[NSNotificationCenter defaultCenter] postNotificationName:FlutterEngineWillDealloc | ||
| object:self | ||
| userInfo:nil]; | ||
|
|
||
| /// nil out weak references. | ||
| [_registrars | ||
| enumerateKeysAndObjectsUsingBlock:^(id key, FlutterEngineRegistrar* registrar, BOOL* stop) { | ||
|
|
@@ -306,7 +311,7 @@ - (void)destroyContext { | |
| self.isolateId = nil; | ||
| _shell.reset(); | ||
| _profiler.reset(); | ||
| _threadHost.Reset(); | ||
| _threadHost.reset(); | ||
| _platformViewsController.reset(); | ||
| } | ||
|
|
||
|
|
@@ -368,10 +373,10 @@ - (void)resetChannels { | |
| } | ||
|
|
||
| - (void)startProfiler { | ||
| FML_DCHECK(!_threadHost.name_prefix.empty()); | ||
| _profiler_metrics = std::make_unique<flutter::ProfilerMetricsIOS>(); | ||
| _profiler = std::make_unique<flutter::SamplingProfiler>( | ||
| _threadHost.name_prefix.c_str(), _threadHost.profiler_thread->GetTaskRunner(), | ||
| FML_DCHECK(!_threadHost->name_prefix.empty()); | ||
| _profiler_metrics = std::make_shared<flutter::ProfilerMetricsIOS>(); | ||
| _profiler = std::make_shared<flutter::SamplingProfiler>( | ||
| _threadHost->name_prefix.c_str(), _threadHost->profiler_thread->GetTaskRunner(), | ||
|
gaaclarke marked this conversation as resolved.
|
||
| [self]() { return self->_profiler_metrics->GenerateSample(); }, kNumProfilerSamplesPerSec); | ||
| _profiler->Start(); | ||
| } | ||
|
|
@@ -550,7 +555,8 @@ - (BOOL)createShell:(NSString*)entrypoint | |
| } | ||
|
|
||
| NSString* threadLabel = [FlutterEngine generateThreadLabel:_labelPrefix]; | ||
| _threadHost = [FlutterEngine makeThreadHost:threadLabel]; | ||
| _threadHost = std::make_shared<flutter::ThreadHost>(); | ||
| *_threadHost = [FlutterEngine makeThreadHost:threadLabel]; | ||
|
|
||
| // Lambda captures by pointers to ObjC objects are fine here because the | ||
| // create call is synchronous. | ||
|
|
@@ -566,9 +572,9 @@ - (BOOL)createShell:(NSString*)entrypoint | |
|
|
||
| flutter::TaskRunners task_runners(threadLabel.UTF8String, // label | ||
| fml::MessageLoop::GetCurrent().GetTaskRunner(), // platform | ||
| _threadHost.raster_thread->GetTaskRunner(), // raster | ||
| _threadHost.ui_thread->GetTaskRunner(), // ui | ||
| _threadHost.io_thread->GetTaskRunner() // io | ||
| _threadHost->raster_thread->GetTaskRunner(), // raster | ||
| _threadHost->ui_thread->GetTaskRunner(), // ui | ||
| _threadHost->io_thread->GetTaskRunner() // io | ||
| ); | ||
|
|
||
| // Create the shell. This is a blocking operation. | ||
|
|
@@ -921,6 +927,42 @@ - (void)waitForFirstFrame:(NSTimeInterval)timeout | |
| }); | ||
| } | ||
|
|
||
| - (FlutterEngine*)spawnWithEntrypoint:(NSString*)entrypoint { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a comment? if you add new features to createShell, please make sure it's mirrored here, and vice versa. Could add some contextual reasoning too. We could merge it into the same API except the Dart APIs only support creating Isolates from other Isolates. Here's a dart SDK github issue.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A change in called functions will often require a change in caller functions. I'm not sure it's worth point that out. I don't know code comments is the right place for design decisions. If you want to suggest something specific we can put it in there. |
||
| assert(_shell); | ||
|
gaaclarke marked this conversation as resolved.
Outdated
|
||
| FlutterEngine* result = | ||
| [[FlutterEngine alloc] initWithName:[_labelPrefix stringByAppendingString:@"-spawn"] | ||
|
gaaclarke marked this conversation as resolved.
Outdated
|
||
| project:_dartProject.get() | ||
| allowHeadlessExecution:_allowHeadlessExecution]; | ||
|
|
||
| flutter::Settings settings = _shell->GetSettings(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we extract parts of this into a private method to share between here and createShell? To minimize the risk of someone updating one and not the other as much as possible?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I did that in |
||
| if (entrypoint) { | ||
|
gaaclarke marked this conversation as resolved.
Outdated
|
||
| settings.advisory_script_entrypoint = entrypoint.UTF8String; | ||
| settings.advisory_script_uri = std::string("main.dart"); | ||
| } else { | ||
| settings.advisory_script_entrypoint = std::string("main"); | ||
| settings.advisory_script_uri = std::string("main.dart"); | ||
| } | ||
|
|
||
| flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view = | ||
| [self](flutter::Shell& shell) { | ||
| [self recreatePlatformViewController]; | ||
| return std::make_unique<flutter::PlatformViewIOS>( | ||
| shell, self->_renderingApi, self->_platformViewsController, shell.GetTaskRunners()); | ||
| }; | ||
|
|
||
| flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer = | ||
| [](flutter::Shell& shell) { return std::make_unique<flutter::Rasterizer>(shell); }; | ||
|
|
||
| std::unique_ptr<flutter::Shell> shell = | ||
| _shell->Spawn(std::move(settings), on_create_platform_view, on_create_rasterizer); | ||
|
|
||
| result->_threadHost = _threadHost; | ||
|
gaaclarke marked this conversation as resolved.
|
||
| result->_profiler = _profiler; | ||
| result->_profiler_metrics = _profiler_metrics; | ||
| [result setupShell:std::move(shell) withObservatoryPublication:NO]; | ||
| return result; | ||
| } | ||
|
|
||
| @end | ||
|
|
||
| @implementation FlutterEngineRegistrar { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.