Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Started handling messages from background isolates.
  • Loading branch information
gaaclarke committed Sep 7, 2022
commit 8dac13cb192f609835f259ad23d5ff6c8fdbda0e
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,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 @@ -1124,6 +1125,8 @@ 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_unittests.cc
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 @@ -100,6 +100,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 @@ -532,12 +532,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