-
Notifications
You must be signed in to change notification settings - Fork 6k
Migrate PlatformMessageHandlerIos to ARC #52226
Changes from all commits
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 |
---|---|---|
|
@@ -4,15 +4,17 @@ | |
|
||
#import "flutter/shell/platform/darwin/ios/platform_message_handler_ios.h" | ||
|
||
#import "flutter/fml/trace_event.h" | ||
#import "flutter/lib/ui/window/platform_message.h" | ||
#import "flutter/shell/platform/darwin/common/buffer_conversions.h" | ||
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h" | ||
#include "flutter/fml/trace_event.h" | ||
#include "flutter/lib/ui/window/platform_message.h" | ||
#include "flutter/lib/ui/window/platform_message_response.h" | ||
#include "flutter/shell/platform/darwin/common/buffer_conversions.h" | ||
|
||
FLUTTER_ASSERT_ARC | ||
|
||
static uint64_t platform_message_counter = 1; | ||
|
||
@interface FLTSerialTaskQueue : NSObject <FlutterTaskQueueDispatch> | ||
@property(nonatomic, strong) dispatch_queue_t queue; | ||
@property(nonatomic, readonly) dispatch_queue_t queue; | ||
@end | ||
|
||
@implementation FLTSerialTaskQueue | ||
|
@@ -24,11 +26,6 @@ - (instancetype)init { | |
return self; | ||
} | ||
|
||
- (void)dealloc { | ||
dispatch_release(_queue); | ||
[super dealloc]; | ||
} | ||
|
||
- (void)dispatch:(dispatch_block_t)block { | ||
dispatch_async(self.queue, block); | ||
} | ||
|
@@ -37,7 +34,7 @@ - (void)dispatch:(dispatch_block_t)block { | |
namespace flutter { | ||
|
||
NSObject<FlutterTaskQueue>* PlatformMessageHandlerIos::MakeBackgroundTaskQueue() { | ||
return [[[FLTSerialTaskQueue alloc] init] autorelease]; | ||
return [[FLTSerialTaskQueue alloc] init]; | ||
} | ||
|
||
PlatformMessageHandlerIos::PlatformMessageHandlerIos( | ||
|
@@ -127,8 +124,8 @@ - (void)dispatch:(dispatch_block_t)block { | |
message_handlers_.erase(channel); | ||
if (handler) { | ||
message_handlers_[channel] = { | ||
.task_queue = fml::scoped_nsprotocol( | ||
[static_cast<NSObject<FlutterTaskQueueDispatch>*>(task_queue) retain]), | ||
.task_queue = | ||
fml::scoped_nsprotocol(static_cast<NSObject<FlutterTaskQueueDispatch>*>(task_queue)), | ||
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. This is similar to the comment on the other PR. ARC doesn't insert an unbalanced retain at a call site and the constructor for the scoped_nsprotocol uses 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.
As noted in my other responses: the version of 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. This one is slightly different since the scoped_nsprotocol isn't consuming a
explicit ScopedTypeRef(
__unsafe_unretained T object = Traits::InvalidValue(),
fml::scoped_policy::OwnershipPolicy policy = fml::scoped_policy::kAssume)
: object_(object) {
if (object_ && policy == fml::scoped_policy::kRetain) {
object_ = Traits::Retain(object_);
}
} In this new code, where would the extra retain come from that will match the one in the destructor for the scoped pointer? I don't think there is one. 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. Oh wait, i see it now: #if !defined(__has_feature) || !__has_feature(objc_arc)
explicit scoped_nsprotocol(NST object = Traits::InvalidValue(),
scoped_policy::OwnershipPolicy policy =
scoped_policy::OwnershipPolicy::kAssume)
: ScopedTypeRef<NST, Traits>(object, policy) {}
#else
explicit scoped_nsprotocol(NST object = Traits::InvalidValue())
: ScopedTypeRef<NST, Traits>(object,
scoped_policy::OwnershipPolicy::kRetain) {}
#endif |
||
.handler = | ||
fml::ScopedBlock<FlutterBinaryMessageHandler>{ | ||
handler, fml::scoped_policy::OwnershipPolicy::kRetain}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, do we need a
__attribute__((ns_returns_autoreleased))
for this method in case it is ever used from MRC? Are we sure that it isn't? Maybe we could add an arc assert in the header.Without it I think ARC reserves the right to return a retained value, expecting the call site to release it. A MRC client would expect it to be autoreleased.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought ARC followed the standard Create/Copy naming rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://clang.llvm.org/docs/AutomaticReferenceCounting.html#conversion-to-retainable-object-pointer-type-of-expressions-with-known-semantics discusses what happens with audited functions, which are new since I had last looked at this in detail. We could add the audit annotation to all of our helpers that follow standard semantics (which I hope is all of them, but we should check) as we go to make it clearer that we know what the semantics are.
So far I can't find discussion of what happens when functions aren't audited, but I'm almost positive that when ARC first rolled out the rule was that it would follow the naming rules (i.e., that everything acted audited). It seems unlikely they would have retroactively changed that since it would have been massively breaking, but if we mark as audited it'll be moot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the hypothetical I was thinking of. This is how the code will look for those that are using this function from MRC.
I checked the output for the following:
The output is
So it looks like autorelease is the default behavior,
ns_returns_autoreleased
seems superfluous in this case.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That matches my recollection that ARC will honor CF-style naming conventions (since your method doesn't start with
Create
orCopy
). But it's weird that I can't find anything that explicitly says that, and sprinklingcf_audited_transfer
on our C functions as we go should be very easy.