Skip to content

Commit

Permalink
Add waitUIThreadIdle service RPC (flutter#3898)
Browse files Browse the repository at this point in the history
In flutter#3833 the `_flutter.listViews` RPC moved from thread based to lock based synchronization.
The thread based synchronization side effect was used by flutter benchmarks in https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/vmservice.dart#L1223 and
https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/run_hot.dart#L156 to ensure the completeness of the restart/reload and so correct timing.

A new RPC `_flutter.flushUIThreadTasks` is introduced to allow the flutter benchmarks to reintroduce thread based synchronization.

Related flutter/flutter#11241
  • Loading branch information
B3rn475 authored Jul 19, 2017
1 parent 99bc6ee commit 53c9a70
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 6 deletions.
36 changes: 33 additions & 3 deletions shell/common/platform_view_service_protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ void PlatformViewServiceProtocol::RegisterHook(bool running_precompiled_code) {
}
Dart_RegisterRootServiceRequestCallback(kRunInViewExtensionName, &RunInView,
nullptr);
// [benchmark helper] Wait for the UI Thread to idle.
Dart_RegisterRootServiceRequestCallback(kFlushUIThreadTasksExtensionName,
&FlushUIThreadTasks, nullptr);
}

const char* PlatformViewServiceProtocol::kRunInViewExtensionName =
Expand Down Expand Up @@ -202,11 +205,10 @@ bool PlatformViewServiceProtocol::ListViews(const char* method,
intptr_t num_params,
void* user_data,
const char** json_object) {
// Ask the Shell for the list of platform views. This will run a task on
// the UI thread before returning.
// Ask the Shell for the list of platform views.
Shell& shell = Shell::Shared();
std::vector<Shell::PlatformViewInfo> platform_views;
shell.WaitForPlatformViewIds(&platform_views);
shell.GetPlatformViewIds(&platform_views);

std::stringstream response;

Expand Down Expand Up @@ -314,4 +316,32 @@ void PlatformViewServiceProtocol::ScreenshotGpuTask(SkBitmap* bitmap) {
canvas->flush();
}

const char* PlatformViewServiceProtocol::kFlushUIThreadTasksExtensionName =
"_flutter.flushUIThreadTasks";

// This API should not be invoked by production code.
// It can potentially starve the service isolate if the main isolate pauses
// at a breakpoint or is in an infinite loop.
//
// It should be invoked from the VM Service and and blocks it until UI thread
// tasks are processed.
bool PlatformViewServiceProtocol::FlushUIThreadTasks(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object) {
ftl::AutoResetWaitableEvent latch;
blink::Threads::UI()->PostTask([&latch]() {
// This task is empty because we just need to synchronize this RPC with the
// UI Thread
latch.Signal();
});

latch.Wait();

*json_object = strdup("{\"type\":\"Success\"}");
return true;
}

} // namespace shell
18 changes: 18 additions & 0 deletions shell/common/platform_view_service_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class PlatformViewServiceProtocol {

private:
static const char* kRunInViewExtensionName;
// It should be invoked from the VM Service and and blocks it until previous
// UI thread tasks are processed.
static bool RunInView(const char* method,
const char** param_keys,
const char** param_values,
Expand All @@ -36,13 +38,29 @@ class PlatformViewServiceProtocol {
const char** json_object);

static const char* kScreenshotExtensionName;
// It should be invoked from the VM Service and and blocks it until previous
// GPU thread tasks are processed.
static bool Screenshot(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
static void ScreenshotGpuTask(SkBitmap* bitmap);

// This API should not be invoked by production code.
// It can potentially starve the service isolate if the main isolate pauses
// at a breakpoint or is in an infinite loop.
//
// It should be invoked from the VM Service and and blocks it until previous
// GPU thread tasks are processed.
static const char* kFlushUIThreadTasksExtensionName;
static bool FlushUIThreadTasks(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
};

} // namespace shell
Expand Down
2 changes: 1 addition & 1 deletion shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ void Shell::GetPlatformViews(
*platform_views = platform_views_;
}

void Shell::WaitForPlatformViewIds(
void Shell::GetPlatformViewIds(
std::vector<PlatformViewInfo>* platform_view_ids) {
std::lock_guard<std::mutex> lk(platform_views_mutex_);
for (auto it = platform_views_.begin(); it != platform_views_.end(); it++) {
Expand Down
4 changes: 2 additions & 2 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Shell {

// List of PlatformViews.

// These APIs must only be accessed on UI thread.
// These APIs can be called from any thread.
void AddPlatformView(const std::shared_ptr<PlatformView>& platform_view);
void PurgePlatformViews();
void GetPlatformViews(
Expand All @@ -58,7 +58,7 @@ class Shell {

// These APIs can be called from any thread.
// Return the list of platform view ids at the time of this call.
void WaitForPlatformViewIds(std::vector<PlatformViewInfo>* platform_view_ids);
void GetPlatformViewIds(std::vector<PlatformViewInfo>* platform_view_ids);

// Attempt to run a script inside a flutter view indicated by |view_id|.
// Will set |view_existed| to true if the view was found and false otherwise.
Expand Down

0 comments on commit 53c9a70

Please sign in to comment.