Re: CF autorelease?
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