• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: CF autorelease?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CF autorelease?


  • Subject: Re: CF autorelease?
  • From: Peter N Lewis <email@hidden>
  • Date: Fri, 24 Apr 2009 13:42:57 +0800

On 24/04/2009, at 9:56 , Wade Tregaskis wrote:

Something I've been using as of late to make CF a little more bearable is the cleanup attribute offered by gcc, e.g.:

static inline void _autoreleaseCFArray(CFArrayRef *array) {
	if (NULL != *array) {
		CFRelease(*array);
	}
}

#define CFAutoreleasedArrayRef __attribute__((cleanup(_autoreleaseCFArray))) CFArrayRef

Unfortunately there's an apparent bug in gcc that requires you to have exact type matches, so you can't make e.g. a generic CFTypeRef variant (unless your variables really are declared as CFTypeRefs). But still, if you're using a particular set of objects a lot, it can save you so much work.


I've used a CFContainer class with good results in my C++ code for Keyboard Maestro. Because of the magic of C++ the container is almost indistinguishable from a raw CF pointer - it takes up the same amount of space and you can pass it to routines requiring a CF pointer as normal.

The code follows, but an example usage might be:

CFContainer<CFStringRef> username = CopyViewText( kKMRegisterWindowUsernameID );
CFContainer<CFStringRef> serial = CopyViewText( kKMRegisterWindowSerialID );
if ( !RegisterUsernameSerial( username, serial ) ) {
return;
}


Where RegisterUsernameSerial takes CFStringRef parameters.

C++ magic ensures the items are released when they go out of scope.

Using the typedef:

typedef CFContainer<CFStringRef> CFCS;

and more C++ magic, you can even do things like:

if ( !RegisterUsernameSerial( CFCS( CopyUsername() ), CFCS( CopySerial() ) ) ) {
return;
}


The copied CFStringRefs are stored in the temporary container until the statement is finished and then released.

You can also do things like

CFContainer<CFStringRef> username = CopyViewText( kKMRegisterWindowUsernameID );
username = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("Thus username is %@"), CFStringRef (username) );


And the original username will be released and a new one stored for later release.

Its not as clean as Cocoa's method, but on the other hand its more efficient than autorelease.

Code follows.

Enjoy,
   Peter.


template<class T> class CFContainer { private: T mRef;

public:
	CFContainer() { mRef = NULL; };
	CFContainer( const T& ref ) { mRef = ref; };
	CFContainer( const CFContainer<T>& ref );
	~CFContainer() { if ( mRef ) CFRelease( mRef ); };

	const T& Get() const { return mRef; };

	T Retain() const { CFRetain( mRef ); return mRef; };

	operator T() const { return mRef; };
	T operator->() const { return mRef; };

	CFContainer<T>& operator= ( const T& ref );
	CFContainer<T>& operator= ( const CFContainer<T>& c );

	bool operator! () { return mRef == NULL; };
	bool Defined() { return mRef != NULL; };
};


template<class T> inline CFContainer<T>::CFContainer( const CFContainer<T>& ref ) { mRef = ref; if ( mRef ) { CFRetain( mRef ); } }


template<class T> CFContainer<T>& CFContainer<T>::operator=( const T& ref ) { if ( mRef ) { CFRelease( mRef ); } mRef = ref; return *this; }

template<class T>
CFContainer<T>&
CFContainer<T>::operator=( const CFContainer<T>& c )
{
	if ( &c != this ) {
		if ( mRef ) {
			CFRelease( mRef );
		}
		mRef = c;
		if ( mRef ) {
			CFRetain( mRef );
		}
	}
	return *this;
}

// Specific case to enable functionality like: CallFunc( CFCS( arg- >CopyName() ) );
typedef CFContainer<CFStringRef> CFCS;


// Stop people accidently releasing CFContainers cast to the underlying ref

extern void CFRelease( CFContainer<SafeCFTypeRef> ref );
extern void CFRelease( CFContainer<CFArrayRef> ref );
extern void CFRelease( CFContainer<CFBagRef> ref );
extern void CFRelease( CFContainer<CFBooleanRef> ref );
extern void CFRelease( CFContainer<CFDataRef> ref );
extern void CFRelease( CFContainer<CFDictionaryRef> ref );
extern void CFRelease( CFContainer<CFNumberRef> ref );
extern void CFRelease( CFContainer<CFSetRef> ref );
extern void CFRelease( CFContainer<CFStringRef> ref );
extern void CFRelease( CFContainer<CFURLRef> ref );
extern void CFRelease( CFContainer<CFUUIDRef> ref );
extern void CFRelease( CFContainer<CFMutableArrayRef> ref );
extern void CFRelease( CFContainer<CFMutableBagRef> ref );
extern void CFRelease( CFContainer<CFMutableDataRef> ref );
extern void CFRelease( CFContainer<CFMutableDictionaryRef> ref );
extern void CFRelease( CFContainer<CFMutableSetRef> ref );
extern void CFRelease( CFContainer<CFMutableStringRef> ref );

--
     Run macros from your iPhone with Keyboard Maestro Control!
         or take a break with Derzle for your iPhone

Keyboard Maestro <http://www.keyboardmaestro.com/> Macros for your Mac
Aragom Space War <http://www.stairways.com/iphone/aragom> Don't get killed!
Derzle <http://www.stairways.com/iphone/derzle> Enjoy a relaxing puzzle.
<http://www.stairways.com/> <http://download.stairways.com/>





_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >CF autorelease? (From: Todd Heberlein <email@hidden>)
 >Re: CF autorelease? (From: Michael Ash <email@hidden>)
 >Re: CF autorelease? (From: Wade Tregaskis <email@hidden>)

  • Prev by Date: RE: Bindings making NSNumberFormatter strange
  • Next by Date: Re: ObjectAlloc and objects that should have been released
  • Previous by thread: Re: CF autorelease?
  • Next by thread: Re: CF autorelease?
  • Index(es):
    • Date
    • Thread