gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Automated Reference Counting (Was: Disappointed by GNUstep)


From: David Chisnall
Subject: Re: Automated Reference Counting (Was: Disappointed by GNUstep)
Date: Tue, 8 Feb 2022 11:01:19 +0000
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.5.1

On 07/02/2022 20:21, Fred Kiefer wrote:
Yes, ARC is a real improvement for application code. Not so much for libraries, 
as GNUstep is. Getting reference counting correct in procedural programming is 
not too hard in most case, but doing so declaratively just seems easier. You 
need to be very careful and provide the correct hints for the compiler to sort 
out things for you. I would expect that a switch here will cost us about two 
years until we got most of the declarations correct. Still the change would be 
worthwhile.
I think you're making up an artificial difference here. The rules for reference 
counting are the same for both application and libraries: If you own/use an 
object retain it, once you no longer own/use it (auto)release it. The tricky 
point just is avoiding cyclic references because they will never be released.
But the real problem (usually) starts when programmers start trying to outsmart those 
simple rules by thinking that some object is already retained by some other 
container/instance variable and they can save some extra CPU cycles (plus the textual 
clutter) by omitting the retain/release calls. And I know what I'm talking about because 
I often enough fall prey to this sort of "optimization". But, as the issue with 
NSPopUpButtonCell shows, I'm not the only one. Note that there is no semantic reason to 
use an unretained reference for the _selectedItem instance variable.
So for -gui the main issue is managing references between objects and their 
delegates and avoiding cyclic reference between parents and children in the 
view hierarchy. And otherwise not compromising the code by the attempting to 
omit retain/release otherwise. For -base, the difficulty is not so much cyclic 
references, but multithreading. You have to be even more careful about 
retaining objects because -- at least without serious locking, which comes with 
its own set of problems -- you cannot be sure that assumptions that hold at 
entry of a method are still valid at the end. So, in a way I feel its even the 
other way around: In libraries ypu should be very sure about proper management 
of ownership, which is better done automatically, whereas in applications you 
can eventually be more sloppy, for instance when you know that the application 
is single threaded.
What you are describing is about what I wanted to say, but obviously failed to 
do. Things are a lot easier in an application as you know what you are aiming 
at. In a library you need to be correct for whatever use case people come up 
with. Doing that is hard. ARC may be able to help you in most cases. Still you 
will have to be very careful and you will need a lot more understanding of the 
implicit semantics. I agree that we should be going that route, we just need to 
be aware that it is a steep road and we need to be careful. Just as you said.

If anything, ARC is more important for libraries than application code, for precisely this reason. ARC explicitly defines ownership (strong, weak, unsafe_unretained) for consumers of a library interface. Things like delegates become weak references and so this is both explicit in the API (the AppKit component does not own the delegate) and less error prone (the reference becomes nil if the object is deallocated).

When Apple moved their Foundation and AppKit implementations to ARC, they reported that they had less source code, smaller binaries, faster code, and fewer bugs. The compiler does a lot of the reference-count-elision things for you and it's easier to define APIs that return strong references and don't leak, so you can significantly reduce autorelease pool pressure.

Many years ago, I ran the -base and -gui code through the ARC Migration Tool (built into clang). I think about half of the code worked with ARC already, a lot of the files needed some small tweaks. The migration tool pointed out all of the places where it couldn't do the automatic translation.

ARC also makes it a lot easier to interop with C++. C++ containers can store Objective-C object pointers in ARC mode and will treat the retain / release calls as copy constructors and destructors. WinObjC made heavy use of this and the last time I tried it replacing `NSMutableDictionary` with a thin wrapper around `std::unordered_map<id>` (with a hash function defined to call `-hash` and the equality function defined to call `-isEqual:`) it was faster than GNUstep's implementation in my tests. I didn't try the same thing with `NSMutableArray` and `std::vector<id>`. I'm told that Apple's implementations do this: implement the containers in C++, wrap them in Objective-C (and there are a lot of high-performance C++ containers with friendly licenses that we could use if the standard library ones aren't adequate).

This was a big part of the reason that I gave up contributing to GNUstep. I could write significantly simpler code that ran faster using Objective-C++ and ARC than I could without either and GNUstep would not accept the less-buggy and faster option. Refactoring code to make it less maintainable so that it could compile with an old compiler and spending time finding bugs that are impossible by construction with ARC felt like a complete waste of my time.

Given that Apple is now focused on SwiftUI, GNUstep is so far behind things like GTK and Qt in completeness, and the license is not one that I'd choose to use given any alternative, I don't imagine that I'd start contributing again even if GNUstep adopted Objective-C++ and ARC, but at least the remaining contributors would be able to achieve more with the same amount of effort.

David




reply via email to

[Prev in Thread] Current Thread [Next in Thread]