From: Charles S. <bas...@ch...> - 2012-07-05 05:17:02
|
On Jul 4, 2012, at 11:33 PM, Alexei Svitkine wrote: > What specific APIs are not available on Tiger that you're using in the new code? I’m currently using the modern pasteboard API to read and write objects from the pasteboard. To make this file compatible with Tiger, I’d basically just have to wrap a few things like this: if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_5) ... new API else ... old API I also used a few block-based APIs here and there — I could just go replace those with something else. > How do you plan to consolidate them? Well, if clip_macosx64.mm is made compatible with Tiger, we could just dump clip_macosx.cpp, rename clip_macosx64.mm to clip_macosx.mm, and add it to both targets. > Btw, I glanced at your code and one comment I have is you seem to use autorelease pools a lot. I wonder if it's really necessary - can you just retain/release manually? Or are you calling APIs that autorelease stuff themselves? Well, let’s say I want to read an object or two off the pasteboard. To do this, I’ll call -[NSPasteboard readObjectsForClasses:options:]. This method returns autoreleased objects — there’s no real way around it. Then, when I want to get a subset of a data or string object, the -subdataWithRange:, -substringWithRange:, etc. APIs return autoreleased objects as well. Plenty of other APIs are like this as well — it’s even a common design pattern to autorelease in your getter accessors, like so: - (id)foo { return [[_foo retain] autorelease]; } I’m not particularly fond of this pattern, but it is pretty much standard practice in the Cocoa world, and is also what Apple’s synthesized accessors do by default, as documented here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17-SW28 On top of all this, even when an API isn’t returning an autoreleased object, you never know what it’s doing internally. It might generate autoreleased objects, it might call other APIs that generate autoreleased objects, etc. Basically what it boils down to is that when you write Cocoa code, you pretty much have to accept that you’re going to get autoreleased objects. The trouble with Basilisk/SheepShaver is we’re running the emulated processor’s run loop, which means we’re never actually going to drop back down to the Cocoa application run loop, which means that the automatic draining that Cocoa does at the end of its internal run loop isn’t going to happen. What *that* means is that if we don’t catch these autoreleased objects in a pool and drain them before we exit, that stuff’s just going to sit on the heap forever and effectively leak. And since I already had pools set up, I didn’t see much harm in using some autoreleased objects of my own here and there, just to reduce a little clutter in the code. If this is bothersome, I can go back and change some of those things — but we do need to have the pools. > Re: your comment in the code about @autoreleasepool: I don't think we'll drop support for gcc any time soon, so the code will have to stay compatible with both, so no point adding a comment about a hypothetical scenario that's not going to happen. > > Still, if you do think the autorelease pools are really required, I suggest making a C++ scoped object that will alloc an autorelease pool in its ctor and release it in its dtor, which will eliminate the need for draining the pool at all the early return points. Yeah, that could work. If we ever did add support for LLVM/clang, we could also make some macros with #ifdefs that would expand to a scoped object with gcc or @autoreleasepool with clang (the nice thing about @autoreleasepool is that it is supposed to have significantly better performance than the NSAutoreleasePool objects). Charles |