> On Dec 19, 2015, at 19:43 , Dave Abrahams via swift-evolution
> <swift-evolution@swift.org> wrote:
>
>>
>> On Dec 19, 2015, at 4:22 PM, Brent Royal-Gordon <br...@architechies.com
>> <mailto:br...@architechies.com>> wrote:
>>
>>>> Mainly, because simply saying "release" or "released" is a bit ambiguous
>>>> to me.Are you saying it *has been* released, or are you saying it *needs
>>>> to be* released?
>>>
>>> But nobody proposed "released" as a method name. In what way is "release"
>>> ambiguous? It's an imperative verb.
>>
>> I guess you're right that "release" is unambiguous, but as you mentioned,
>> it's also strange to release a value and then use it.
>
> Yes. I think there are no really great choices here (at least not so far) so
> the question is whether that strangeness is enough of a problem to outweigh
> the points release() has in its favor. What do you think?
>
>> I think what I'm trying to get at here is that I prefer to think of the
>> operations on Unmanaged as "explain to ARC how it should handle this
>> object", rather than "do some manual operations so that ARC will do the
>> right thing". Maybe the current Unmanaged design has shown the limitations
>> of that approach, though.
>
> Not at all; the Unmanaged design—at least in my best understanding of its
> intent—is firmly in the imperative/manual operations camp. I wanted to do
> something more declarative, but the "I want to manage the reference that I
> claim was passed to me at +1" operation is side-effectful. Are we really
> comfortable with hiding that fact?
>
>>> But you applied "take" to both of them? One of them is idempotent while
>>> the other is not.
>>
>> The preferred way to use Unmanaged is that you immediately convert it to a
>> managed reference without ever storing it or using it in any other way. That
>> means you should immediately call either the retain-and-return operation or
>> the don't-retain-and-return operation. Both of these should only ever be
>> called once. You may instead choose to keep the reference Unmanaged and
>> manually retain, release, and access it, but best practices discourage that.
>
> As I said in my original post, I'm ambivalent about the importance of
> highlighting the distinctions of safety and idempotence between these
> methods, but even if they're named similarly I don't see any merit in
> starting with "take." One thing I really dislike about is that the receiver,
> the UnsafeReference, isn't "taking" anything. The *caller* might be said to
> be taking something from the UnsafeReference, but only in the "returned at
> +1" case.
>
> How I see it: along with the UnsafeReference the called CF function either
> notionally
> a) gives (possibly-shared) ownership of the object directly to the caller, or
> b) gives the caller a token that allows him to get (shared) ownership of the
> object
>
> In case a), the caller needs to ask the UnsafeReference to transfer (or
> "release") that ownership into a strong reference, and. In case b), the
> caller needs to explicitly get (shared) ownership.
>
> If this description doesn't sound right to you, please try to correct it;
> that may help me understand your perspective better.
For the record, I have previously talked with Dave about this in person. The
conclusion I came to was that "[foo release]" and "CFRelease(foo)" are saying
"I release [my hold on] 'foo'", but std::unique_ptr::release
<http://en.cppreference.com/w/cpp/memory/unique_ptr/release> is saying "please
release your referent to me". The directionality being different is what
created so much cognitive dissonance for me.
I'm still one of those who really doesn't like plain 'release' as a name.
Putting "release" in the name is fine (to Greg's point about
CFBridgingRelease), but 'release' on its own has way too much baggage for me.
(To the point where I have to double-check mentally that it's what I really
want when I'm working with std::unique_ptr.) Maybe that's historical, though—a
pure Swift programmer has never called CFRelease.
To Brent's point about putting "Create" somewhere in there: the other use of
Unmanaged is "safely" getting managed references through 'void *' "context
pointers". In this case you're balancing a retain you performed. (That said,
I'm also against the general pattern of passing references through context
pointers, because it's very hard to ensure that they get cleaned up, if
retained, or kept alive, if unretained.)
Oh, and there's one last use of Unmanaged: fields of structs. These are rare
but they do exist.
Jordan
P.S. There is, in fact, a CFBridgingRetain, for going from ObjC ARC to CF
manual ref-counting. I'm not sure why Greg didn't mention it.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution