[swift-evolution] RFC: Proposed rewrite of Unmanaged<T>
T.J. Usiyan
griotspeak at gmail.com
Thu Dec 17 20:23:56 CST 2015
I think I see what you mean about parity. `.object` can be called multiple
times, then? Why not make `release()` slightly more verbose since it should
only be called once anyway? Something along the lines of
`.releaseAndReturnObject` or … something slightly less verbose.
My main point of contention with `.release()` is that it has the *exact*
same name as a method from the MRC strategy. Maybe this is a silly point,
but this overlap could further complicate teaching how ARC works and in
what ways it is based on MRC conventions. I am not of the opinion that ARC
is fundamentally more difficult to understand than MRC, but I do believe
that it takes a very particular kind of faith now that we don't get to
manually write the retains and releases. This is completely worth it, in my
opinion, but I want to avoid making it *more* confusing to explain what
ARC doing at compile time.
TJ
On Thu, Dec 17, 2015 at 9:13 PM, Dave Abrahams <dabrahams at apple.com> wrote:
> Thanks very much for the quick feedback TJ,
>
> On Dec 17, 2015, at 5:52 PM, T.J. Usiyan <griotspeak at gmail.com> wrote:
>
> Hello Dave,
>
> I like this change and think that it will help clarify the purpose of the
> type. As I was reading, the only concern that I had was the name. Could you
> please provide some of the names that you all have considered
>
>
> Honestly, I am sorry to say, we did that exercise almost a month ago and I
> don’t remember the ones we discussed.
>
> so that we can avoid suggesting the same things? My suggestion is
>
> CF*Something*(*arguments…*).retainedObject() // when the result is
> returned at +1
>
> or
>
> CF*Something*(*arguments…*).unretainedObject() // when the result
> is returned at +0
>
> on the premise that the important bit of information is whether or not the
> object is already retained. No matter what names are chosen, that is the
> data which determines which method to call. `retainedObject |
> unretainedObject`, `takeRetainedObject | takeUnretainedObject`, or
> `retained | unretained` all seem like viable options (that you have
> probably considered).
>
>
>
> Some issues with these names:
>
>
> - The “ed/ing” rule
> <https://swift.org/documentation/api-design-guidelines.html#be-grammatical> makes
> these names suggest that the accessors are idempotent, but the first one
> must be called exactly once. That name should really be an active verb
> since it is state-changing.
> - “retainedObject” also suggests that it’s returning some underlying
> object after retaining it, which is almost the opposite of what that API
> does… and vice-versa for “unretainedObject"
> - Also, the object “has been retained” in all cases, or it would have
> been deallocated. The question is whether the object would leak if we fail
> to call release on it
> - Nothing in these names connect them to what the documentation says
> about the functions that return Unmanaged, so it’s hard to know which one
> to call
> - The second API is objectively safer than the first one (which causes
> undefined behavior when overused and only leaks when underused). The API I
> proposed makes it clear that they are not peers, where yours implies
> parity—though I am of two minds about the value of representing the lack of
> parity.
>
>
> You may legitimately argue that any of these concerns are unimportant, but
> those are the ones that come up for me.
>
> TJ
>
>
> On Thu, Dec 17, 2015 at 8:37 PM, Dave Abrahams via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Hi Everybody,
>>
>> We’ve been working on a rewrite of the Unmanaged<T> component, and are
>> soliciting comments. First, a little background:
>>
>>
>> - Unmanaged
>> <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID79> is
>> primarily used as a return type from imported CoreFoundation functions that
>> haven’t been annotated with reference-counting semantic information
>> - A secondary known use-case is as a vehicle for creating a
>> COpaquePointer containing a reference’s bits, e.g. for when you need to
>> pass a reference through C APIs that use “void*” as a universal “give me
>> some info and I’ll give it back to your callback” mechanism.
>>
>>
>>
>> - We saw several problems with Unmanaged that we wanted to fix:
>> - It was poorly-named (the reference is managed by *somebody*, we
>> just aren't representing that management in the type system).
>> - Its interface was much broader than it needs to be to cover the
>> use-cases
>> - The purpose of many of its APIs was unclear
>> - Its documentation was vague and hard to understand.
>> - It didn’t establish a maximally-safe usage pattern for handling
>> the results of un-annotated CoreFoundation functions.
>>
>>
>> The code for the proposed replacement, called UnsafeReference, is here
>> <https://github.com/dabrahams/swift/blob/6eb86b48d150342709da3f3be9c738df23382866/stdlib/public/core/UnsafeReference.swift>,
>> and a commit that updates Swift to use it is here
>> <https://github.com/dabrahams/swift/commit/6eb86b48d150342709da3f3be9c738df23382866>
>> .
>>
>> Maximally Safe Usage
>>
>> The recommended usage pattern for handling an UnsafeReference<T>
>> returned by a function CF*Something* is to always use the T instance
>> produced by one of the forms:
>>
>> CF*Something*(*arguments…*).release() // when the result is returned
>> at +1
>>
>> or
>>
>> CF*Something*(*arguments…*).object // when the result is returned
>> at +0
>>
>> In other words, turn the UnsafeReference<T> into a safe T as quickly as
>> possible, and never store the UnsafeReference<T> in a variable so that
>> it can’t be (mis)used thereafter.
>>
>> Points of Discussion
>>
>> We’re interested in any feedback you might have, but there are a few
>> points we’d especially like to address:
>>
>>
>> - The name of the release() method has been contentious.
>> - 👍: Documentation—or naming conventions such as the “create rule
>> <https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html>”—normally
>> says something like “you are responsible for releasing the result” in those
>> cases where release() must be called, so there’s a very direct way
>> to know which variant of the recommended usage pattern to employ.
>> - 👎: Some people who are very familiar with existing manual
>> retain/release programming find the recommended usage pattern really
>> counter-intuitive because they're “using something after calling release on
>> it,” which one never does in Objective-C.
>> - The alternative names we’ve been able to think of so far are
>> verbose, clumsy, and don’t match up with anything in the documentation of
>> the called function, so this seems like a really hard naming problem.
>> Better ideas from the community would be most welcome here.
>> - We’re not sure about the terminology
>> <https://github.com/dabrahams/swift/blob/6eb86b48d150342709da3f3be9c738df23382866/stdlib/public/core/UnsafeReference.swift#L27> (Unretained/Retained/Released) used
>> to precisely describe the semantics of UnsafeReference. We’d like to
>> know if these terms make sense to you or whether you have better ideas.
>> - We want to know whether the usage pattern recommended above works
>> for you.
>> - We want to know if the API is sufficiently broad or if there are
>> things you currently get—and need—from Unmanaged that we’ve left out.
>>
>>
>> Thanks in advance,
>>
>> -Dave
>>
>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
> -Dave
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151217/0d6753cd/attachment.html>
More information about the swift-evolution
mailing list