Skip to content
This repository has been archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
Started handling messages from background isolates.
Browse files Browse the repository at this point in the history
  • Loading branch information
gaaclarke committed Aug 12, 2022
1 parent 457a9de commit f303fba
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 19 deletions.
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ FILE: ../../../flutter/fml/memory/task_runner_checker.cc
FILE: ../../../flutter/fml/memory/task_runner_checker.h
FILE: ../../../flutter/fml/memory/task_runner_checker_unittest.cc
FILE: ../../../flutter/fml/memory/thread_checker.h
FILE: ../../../flutter/fml/memory/threadsafe_unique_ptr.h
FILE: ../../../flutter/fml/memory/weak_ptr.h
FILE: ../../../flutter/fml/memory/weak_ptr_internal.cc
FILE: ../../../flutter/fml/memory/weak_ptr_internal.h
Expand Down Expand Up @@ -1054,6 +1055,8 @@ FILE: ../../../flutter/lib/ui/window/platform_message_response.cc
FILE: ../../../flutter/lib/ui/window/platform_message_response.h
FILE: ../../../flutter/lib/ui/window/platform_message_response_dart.cc
FILE: ../../../flutter/lib/ui/window/platform_message_response_dart.h
FILE: ../../../flutter/lib/ui/window/platform_message_response_dart_port.cc
FILE: ../../../flutter/lib/ui/window/platform_message_response_dart_port.h
FILE: ../../../flutter/lib/ui/window/pointer_data.cc
FILE: ../../../flutter/lib/ui/window/pointer_data.h
FILE: ../../../flutter/lib/ui/window/pointer_data_packet.cc
Expand Down
111 changes: 111 additions & 0 deletions fml/memory/threadsafe_unique_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// 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.

#ifndef FLUTTER_FML_THREADSAFE_UNIQUE_PTR_H_
#define FLUTTER_FML_THREADSAFE_UNIQUE_PTR_H_

#include <memory>
#include <mutex>

#include "flutter/fml/macros.h"

namespace fml {

/// A single-owner smart pointer that allows weak references that can be
/// accessed on different threads.
/// This smart-pointer makes the following guarantees:
/// * There is only ever one threadsafe_unique_ptr per object.
/// * The object is deleted when ~threadsafe_unique_ptr() is called.
/// * The object will not be deleted whilst another thread has a lock_ptr.
/// * The thread that owns the object can access it without a lock.
/// WARNING: weak_ptr's should only be used to invoke thread-safe methods.
template <typename T>
class threadsafe_unique_ptr {
private:
struct Data {
Data(std::unique_ptr<T>&& arg_ptr) : ptr(std::move(arg_ptr)) {}
std::unique_ptr<T> ptr;
std::mutex mutex;
};

public:
threadsafe_unique_ptr()
: data_(new Data(std::unique_ptr<T>())), fast_ptr_(nullptr) {}

threadsafe_unique_ptr(std::unique_ptr<T>&& ptr)
: data_(new Data(std::move(ptr))) {
fast_ptr_ = data_->ptr.get();
}

threadsafe_unique_ptr(threadsafe_unique_ptr<T>&& ptr)
: data_(std::move(ptr.data_)), fast_ptr_(std::move(ptr.fast_ptr_)) {}

threadsafe_unique_ptr& operator=(threadsafe_unique_ptr&& rvalue) {
data_ = std::move(rvalue.data_);
fast_ptr_ = std::move(rvalue.fast_ptr_);
return *this;
}

~threadsafe_unique_ptr() {
if (data_) {
std::scoped_lock lock(data_->mutex);
data_->ptr.reset();
}
}

T* operator->() const { return fast_ptr_; }

T* get() const { return fast_ptr_; }

operator bool() const { return fast_ptr_ != nullptr; }

class lock_ptr;

/// A non-owning smart pointer for a `threadsafe_unique_ptr`.
class weak_ptr {
public:
weak_ptr() {}

weak_ptr(std::weak_ptr<Data> weak_ptr) : weak_ptr_(weak_ptr) {}

private:
friend class lock_ptr;
std::weak_ptr<Data> weak_ptr_;
};

/// A temporary owning smart pointer for a `threadsafe_unique_ptr`. This
/// guarantees that the object will not be deleted while in scope.
class lock_ptr {
public:
lock_ptr(const weak_ptr& weak) : strong_ptr_(weak.weak_ptr_.lock()) {
if (strong_ptr_) {
lock_ = std::unique_lock(strong_ptr_->mutex);
}
}

T* operator->() { return strong_ptr_ ? strong_ptr_->ptr.get() : nullptr; }

operator bool() const {
return strong_ptr_ ? static_cast<bool>(strong_ptr_->ptr) : false;
}

private:
FML_DISALLOW_COPY_AND_ASSIGN(lock_ptr);
std::shared_ptr<Data> strong_ptr_;
std::unique_lock<std::mutex> lock_;
};

weak_ptr GetWeakPtr() const { return weak_ptr(data_); }

private:
FML_DISALLOW_COPY_AND_ASSIGN(threadsafe_unique_ptr);
std::shared_ptr<Data> data_;
// Clients that own the threadsafe_unique_ptr can access the pointer directly
// since there is no risk that it will be deleted whilst being accessed.
T* fast_ptr_;
};

} // namespace fml

#endif // FLUTTER_FML_THREADSAFE_UNIQUE_PTR_H_
2 changes: 2 additions & 0 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ source_set("ui") {
"window/platform_message_response.h",
"window/platform_message_response_dart.cc",
"window/platform_message_response_dart.h",
"window/platform_message_response_dart_port.cc",
"window/platform_message_response_dart_port.h",
"window/pointer_data.cc",
"window/pointer_data.h",
"window/pointer_data_packet.cc",
Expand Down
3 changes: 3 additions & 0 deletions lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ typedef CanvasPath Path;
V(PlatformConfigurationNativeApi::ComputePlatformResolvedLocale, 1) \
V(PlatformConfigurationNativeApi::SendPlatformMessage, 3) \
V(PlatformConfigurationNativeApi::RespondToPlatformMessage, 2) \
V(PlatformConfigurationNativeApi::RegisterRootIsolate, 0) \
V(PlatformConfigurationNativeApi::RegisterBackgroundIsolate, 1) \
V(PlatformConfigurationNativeApi::SendPortPlatformMessage, 4) \
V(DartRuntimeHooks::Logger_PrintDebugString, 1) \
V(DartRuntimeHooks::Logger_PrintString, 1) \
V(DartRuntimeHooks::ScheduleMicrotask, 1) \
Expand Down
28 changes: 27 additions & 1 deletion lib/ui/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,38 @@ class PlatformDispatcher {
}
}

String? _sendPlatformMessage(String name,PlatformMessageResponseCallback? callback, ByteData? data) =>
String? _sendPlatformMessage(String name, PlatformMessageResponseCallback? callback, ByteData? data) =>
__sendPlatformMessage(name, callback, data);

@FfiNative<Handle Function(Handle, Handle, Handle)>('PlatformConfigurationNativeApi::SendPlatformMessage')
external static String? __sendPlatformMessage(String name, PlatformMessageResponseCallback? callback, ByteData? data);

void sendPortPlatformMessage(
String name,
ByteData? data,
int identifier,
SendPort port) {
final String? error =
_sendPortPlatformMessage(name, identifier, port.nativePort, data);
if (error != null) {
throw Exception(error);
}
}

String? _sendPortPlatformMessage(String name, int identifier, int port, ByteData? data) =>
__sendPortPlatformMessage(name, identifier, port, data);

@FfiNative<Handle Function(Handle, Handle, Handle, Handle)>('PlatformConfigurationNativeApi::SendPortPlatformMessage')
external static String? __sendPortPlatformMessage(String name, int identifier, int port, ByteData? data);

int registerRootIsolate() => __registerRootIsolate();
@FfiNative<Int64 Function()>('PlatformConfigurationNativeApi::RegisterRootIsolate')
external static int __registerRootIsolate();

void registerBackgroundIsolate(int rootIsolateId) => __registerBackgroundIsolate(rootIsolateId);
@FfiNative<Void Function(Int64)>('PlatformConfigurationNativeApi::RegisterBackgroundIsolate')
external static void __registerBackgroundIsolate(int rootIsolateId);

/// Called whenever this platform dispatcher receives a message from a
/// platform-specific plugin.
///
Expand Down
24 changes: 23 additions & 1 deletion lib/ui/ui_dart_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,22 @@ UIDartState* UIDartState::Current() {
}

void UIDartState::SetPlatformConfiguration(
std::unique_ptr<PlatformConfiguration> platform_configuration) {
fml::threadsafe_unique_ptr<PlatformConfiguration> platform_configuration) {
FML_DCHECK(IsRootIsolate());
platform_configuration_ = std::move(platform_configuration);
if (platform_configuration_) {
platform_configuration_->client()->UpdateIsolateDescription(debug_name_,
main_port_);
}
}

void UIDartState::SetWeakPlatformConfiguration(
fml::threadsafe_unique_ptr<PlatformConfiguration>::weak_ptr
platform_configuration) {
FML_DCHECK(!IsRootIsolate());
weak_platform_configuration_ = platform_configuration;
}

const TaskRunners& UIDartState::GetTaskRunners() const {
return context_.task_runners;
}
Expand Down Expand Up @@ -214,4 +222,18 @@ bool UIDartState::enable_skparagraph() const {
return enable_skparagraph_;
}

void UIDartState::HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) {
if (platform_configuration_) {
platform_configuration_->client()->HandlePlatformMessage(
std::move(message));
} else {
fml::threadsafe_unique_ptr<PlatformConfiguration>::lock_ptr lock(
weak_platform_configuration_);
if (lock) {
lock->client()->HandlePlatformMessage(std::move(message));
}
}
}

} // namespace flutter
20 changes: 18 additions & 2 deletions lib/ui/ui_dart_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "flutter/common/task_runners.h"
#include "flutter/flow/skia_gpu_object.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/memory/threadsafe_unique_ptr.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/lib/ui/io_manager.h"
Expand All @@ -30,6 +31,7 @@ namespace flutter {
class FontSelector;
class ImageGeneratorRegistry;
class PlatformConfiguration;
class PlatformMessage;

class UIDartState : public tonic::DartState {
public:
Expand Down Expand Up @@ -106,6 +108,18 @@ class UIDartState : public tonic::DartState {
return platform_configuration_.get();
}

fml::threadsafe_unique_ptr<PlatformConfiguration>::weak_ptr
GetWeakPlatformConfiguration() const {
return platform_configuration_ ? platform_configuration_.GetWeakPtr()
: weak_platform_configuration_;
}

void SetWeakPlatformConfiguration(
fml::threadsafe_unique_ptr<PlatformConfiguration>::weak_ptr
platform_configuration);

void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message);

const TaskRunners& GetTaskRunners() const;

void ScheduleMicrotask(Dart_Handle handle);
Expand Down Expand Up @@ -167,7 +181,7 @@ class UIDartState : public tonic::DartState {
~UIDartState() override;

void SetPlatformConfiguration(
std::unique_ptr<PlatformConfiguration> platform_configuration);
fml::threadsafe_unique_ptr<PlatformConfiguration> platform_configuration);

const std::string& GetAdvisoryScriptURI() const;

Expand All @@ -180,7 +194,9 @@ class UIDartState : public tonic::DartState {
Dart_Port main_port_ = ILLEGAL_PORT;
const bool is_root_isolate_;
std::string debug_name_;
std::unique_ptr<PlatformConfiguration> platform_configuration_;
fml::threadsafe_unique_ptr<PlatformConfiguration> platform_configuration_;
fml::threadsafe_unique_ptr<PlatformConfiguration>::weak_ptr
weak_platform_configuration_;
tonic::DartMicrotaskQueue microtask_queue_;
UnhandledExceptionCallback unhandled_exception_callback_;
LogMessageCallback log_message_callback_;
Expand Down
Loading

0 comments on commit f303fba

Please sign in to comment.