> On Dec 17, 2015, at 7:32 PM, Félix Cloutier <[email protected]> wrote:
> 
> If this can be used as any reference, I wrote some code to help interoperate 
> with Python in C++.

BTDT; see http://boost.org/libs/python :-)

> The Python API inconsistently returns references with a +0 or +1 count. I use 
> macros called TAKEREF (when the object is returned with a +1 count) and 
> ADDREF (when it's returned with +0) to create smart wrappers. The wrapper 
> will always decrement the reference count during destruction.
> 
> I find it unambiguous: you need to add a reference if you're going to take 
> one away at destruction, so ADD; but if the object is returned with a +1 
> count, you can just TAKE the reference. It coincidentally does not borrow 
> terminology from Objective-C's memory management system.

But it does tread on an area we’re trying very hard to clear up in Swift’s use 
of terminology: what does the word “take” mean?  In fact the “take” problem was 
partly caused by the existing design of Unmanaged.  Also, while unambiguous, 
it’s a very low-level description of what’s happening, that doesn’t much help 
the user reading the documentation of a CF function to answer the “which one do 
I use?” question unless s/he’s already experienced with how to map what it says 
in that docs onto the use of ADDREF/TAKEREF.

>> Le 17 déc. 2015 à 21:23:56, T.J. Usiyan via swift-evolution 
>> <[email protected] <mailto:[email protected]>> a écrit :
>> 
>> 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 <[email protected] 
>> <mailto:[email protected]>> wrote:
>> Thanks very much for the quick feedback TJ, 
>> 
>>> On Dec 17, 2015, at 5:52 PM, T.J. Usiyan <[email protected] 
>>> <mailto:[email protected]>> 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 
>>> 
>>>     CFSomething(arguments…).retainedObject() // when the result is returned 
>>> at +1
>>> 
>>> or
>>> 
>>>     CFSomething(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 
>>> <[email protected] <mailto:[email protected]>> 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 CFSomething is to always use the T instance produced by one 
>>> of the forms:
>>> 
>>>     CFSomething(arguments…).release() // when the result is returned at +1
>>> 
>>> or
>>> 
>>>     CFSomething(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
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> 
>> 
>> -Dave
>> 
>> 
>> 
>> 
>>  _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

-Dave



_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to