Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CF_RETURNS_RETAINED or CF_RETURNS_NOT_RETAINED: which to use when?

I am unsure whether to use CF_RETURNS_RETAINED or CF_RETURNS_NOT_RETAINED for my custom function returning a CFDataProviderRef.

According to the documentation at the location where the macros are defined, both should only used in exceptional circumstances, and the correct fix should be to fix my naming convention. However The swift/objective-c documentation suggests using them to annotate any function returning a CoreFoundation pointer, without really explaining when to use which --- if I don't annotate them I need to manually specify the behaviour every time in the swift code.

Further documentation I could find explains how one uses a ARC value of +1 and the other of 0, however I'm afraid that doesn't help me much in understanding.

My questions:

  1. Should I be using them at all, or improve my naming as Base.h suggests?
  2. What is the exact naming convention that is being used there?
  3. Am I correct in assuming that I should use one if I want the memory used by the returned object free'd as soon as it goes out of scope in the caller, and the other if I don't want this to happen (because I use a pointer to it somewhere else, or clean up myself)?
  4. All my function does is return a CFDataProviderRef that I got from a call to CGDataProviderCreateSequential. I guess that means I want the the behaviour as CGDataProviderCreateSequential (right?). How can I find whether that function uses CF_RETURNS_RETAINED or CF_RETURNS_NOT_RETAINED (it's not there in the CGDataProvider.h file)?
like image 650
Claude Avatar asked Dec 09 '22 07:12

Claude


1 Answers

This is all about ownership. The naming convention is that of Core Foundation, which is described here. The Create Rule says that functions with "Create" and "Copy" in their name leave the caller with ownership of the returned object (although not necessarily sole ownership). That means that the caller has a responsibility to eventually release the returned object using CFRelease(). The Get Rule says that functions other than creation or copy functions do not give the caller ownership of the object, so the caller must not call CFRelease() on it (except to balance any explicit calls to CFRetain(), of course).

If a function is semantically a creation or copy function which returns ownership to the caller, but its name doesn't indicate that, you should use CF_RETURNS_RETAINED to indicate that. Similarly, if a function's name contains "Create" or "Copy" but it doesn't have semantics matching the Create Rule, you should use CF_RETURNS_NOT_RETAINED to indicate that. (Try to avoid this.)

Since your code is calling CGDataProviderCreateSequential() and since that has "Create" in the name, your code is responsible for releasing the returned CGDataProvider object. If you release it right there in your function, then your caller can't get access to it. You want to return the object to the caller. You also want to pass the responsibility for releasing the object to the caller, since you don't know when the caller will be done with it. So, you should name your function with "Create" in its name to indicate both to the caller and to automated systems that the caller receives responsibility for releasing the object. Alternatively, you could annotate your function with CF_RETURNS_RETAINED to signify that, but following the naming convention is better.

It's possible that Swift only respects the naming convention for system headers. I don't know. In that case, you'd have to annotate with CF_RETURNS_RETAINED even if your function has "Create" in its name. There's no harm in annotating a function whose name already follows the convention. It's redundant but harmless.

like image 148
Ken Thomases Avatar answered Dec 11 '22 07:12

Ken Thomases