X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b4e0eabd78bfbd7434cf7b959f9449439e0d1dfe..fba05595e6cca40763f8ead119c7ad61cb01e0e4:/include/wx/mac/corefoundation/cfref.h diff --git a/include/wx/mac/corefoundation/cfref.h b/include/wx/mac/corefoundation/cfref.h index 29485f4325..fb84f0fc5c 100644 --- a/include/wx/mac/corefoundation/cfref.h +++ b/include/wx/mac/corefoundation/cfref.h @@ -2,10 +2,10 @@ // Name: wx/mac/corefoundation/cfref.h // Purpose: wxCFRef template class // Author: David Elliott -// Modified by: +// Modified by: Stefan Csomor // Created: 2007/05/10 // RCS-ID: $Id$ -// Copyright: (c) 2007 David Elliott +// Copyright: (c) 2007 David Elliott , Stefan Csomor // Licence: wxWindows licence // Notes: See http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/index.html ///////////////////////////////////////////////////////////////////////////// @@ -17,22 +17,142 @@ #ifndef _WX_MAC_COREFOUNDATION_CFREF_H__ #define _WX_MAC_COREFOUNDATION_CFREF_H__ -#include +// #include +/* Don't include CFBase.h such that this header can be included from public + * headers with minimal namespace pollution. + * Note that Darwin CF uses extern for CF_EXPORT. If we need this on Win32 + * or non-Darwin Mac OS we'll need to define the appropriate __declspec. + */ +extern "C" { +typedef const void *CFTypeRef; +extern /* CF_EXPORT */ +CFTypeRef CFRetain(CFTypeRef cf); +extern /* CF_EXPORT */ +void CFRelease(CFTypeRef cf); +} // extern "C" -/*! @class wxCFRef + +/*! @function wxCFRelease + @abstract A CFRelease variant that checks for NULL before releasing. + @discussion The parameter is template not for type safety but to ensure the argument + is a raw pointer and not a ref holder of any type. +*/ +template +inline void wxCFRelease(Type *r) +{ + if ( r != NULL ) + ::CFRelease((CFTypeRef)r); +} + +/*! @function wxCFRetain + @abstract A typesafe CFRetain variant that checks for NULL. +*/ +template +inline Type* wxCFRetain(Type *r) +{ + // NOTE(DE): Setting r to the result of CFRetain improves efficiency on both x86 and PPC + // Casting r to CFTypeRef ensures we are calling the real C version defined in CFBase.h + // and not any possibly templated/overloaded CFRetain. + if ( r != NULL ) + r = (Type*)::CFRetain((CFTypeRef)r); + return r; +} + +template +class wxCFRef; + +/*! @class wxCFWeakRef @templatefield refType The CF reference type (e.g. CFStringRef, CFRunLoopRef, etc.) It should already be a pointer. This is different from shared_ptr where the template parameter is the pointee type. - @discussion Properly retains/releases reference to CoreFoundation objects + @discussion Wraps a raw pointer without any retain or release. + Provides a way to get what amounts to a raw pointer from a wxCFRef without + using a raw pointer. Unlike a raw pointer, constructing a wxCFRef from this + class will cause it to be retained because it is assumed that a wxCFWeakRef + does not own its pointer. */ template -class wxCFRef +class wxCFWeakRef { - // Declare wxCFRef as a friend so that the conversion constructor can access m_ptr directly + template + friend wxCFWeakRef static_cfref_cast(const wxCFRef &otherRef); +public: + /*! @method wxCFWeakRef + @abstract Creates a NULL reference + */ + wxCFWeakRef() + : m_ptr(NULL) + {} + + // Default copy constructor is fine. + // Default destructor is fine but we'll set NULL to avoid bugs + ~wxCFWeakRef() + { m_ptr = NULL; } + + // Do not implement a raw-pointer constructor. + + /*! @method wxCFWeakRef + @abstract Copies another ref holder where its type can be converted to ours + @templatefield otherRefType Any type held by another wxCFWeakRef. + @param otherRef The other weak ref holder to copy. + @discussion This is merely a copy or implicit cast. + */ template - friend class wxCFRef; + wxCFWeakRef(const wxCFWeakRef& otherRef) + : m_ptr(otherRef.get()) // Implicit conversion from otherRefType to refType should occur + {} + /*! @method wxCFWeakRef + @abstract Copies a strong ref holder where its type can be converted to ours + @templatefield otherRefType Any type held by a wxCFRef. + @param otherRef The strong ref holder to copy. + @discussion This ref is merely a pointer copy, the strong ref still holds the pointer. + */ + template + wxCFWeakRef(const wxCFRef& otherRef) + : m_ptr(otherRef.get()) // Implicit conversion from otherRefType to refType should occur + {} + /*! @method get + @abstract Explicit conversion to the underlying pointer type + @discussion Allows the caller to explicitly get the underlying pointer. + */ + refType get() const + { return m_ptr; } + + /*! @method operator refType + @abstract Implicit conversion to the underlying pointer type + @discussion Allows the ref to be used in CF function calls. + */ + operator refType() const + { return m_ptr; } + +protected: + /*! @method wxCFWeakRef + @abstract Constructs a weak reference to the raw pointer + @templatefield otherType Any type. + @param p The raw pointer to assume ownership of. May be NULL. + @discussion This method is private so that the friend static_cfref_cast can use it + */ + template + explicit wxCFWeakRef(otherType *p) + : m_ptr(p) // Implicit conversion from otherType* to refType should occur. + {} + + /*! @var m_ptr The raw pointer. + */ + refType m_ptr; +}; + +/*! @class wxCFRef + @templatefield refType The CF reference type (e.g. CFStringRef, CFRunLoopRef, etc.) + It should already be a pointer. This is different from + shared_ptr where the template parameter is the pointee type. + @discussion Properly retains/releases reference to CoreFoundation objects +*/ +template +class wxCFRef +{ public: /*! @method wxCFRef @abstract Creates a NULL reference @@ -65,11 +185,8 @@ public: the object will be explicitly retained by this new ref. */ wxCFRef(const wxCFRef& otherRef) - : m_ptr(otherRef.m_ptr) - { - if(m_ptr != NULL) - CFRetain(m_ptr); - } + : m_ptr(wxCFRetain(otherRef.m_ptr)) + {} /*! @method wxCFRef @abstract Copies a ref holder where its type can be converted to ours @@ -80,11 +197,21 @@ public: */ template wxCFRef(const wxCFRef& otherRef) - : m_ptr(otherRef.m_ptr) // Implicit conversion from otherRefType to refType should occur - { - if(m_ptr != NULL) - CFRetain(m_ptr); - } + : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur + {} + + /*! @method wxCFRef + @abstract Copies a weak ref holder where its type can be converted to ours + @templatefield otherRefType Any type held by a wxCFWeakRef. + @param otherRef The weak ref holder to copy. + @discussion Ownership will be taken by this newly created ref. That is, + the object will be explicitly retained by this new ref. + Ownership is most likely shared with some other ref as well. + */ + template + wxCFRef(const wxCFWeakRef& otherRef) + : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur + {} /*! @method ~wxCFRef @abstract Releases (potentially shared) ownership of the ref. @@ -102,10 +229,8 @@ public: */ wxCFRef& operator=(const wxCFRef& otherRef) { - if(otherRef.m_ptr != NULL) - CFRetain(otherRef.m_ptr); - if(m_ptr != NULL) - CFRelease(m_ptr); + wxCFRetain(otherRef.m_ptr); + wxCFRelease(m_ptr); m_ptr = otherRef.m_ptr; return *this; } @@ -120,11 +245,9 @@ public: template wxCFRef& operator=(const wxCFRef& otherRef) { - if(otherRef.m_ptr != NULL) - CFRetain(otherRef.m_ptr); - if(m_ptr != NULL) - CFRelease(m_ptr); - m_ptr = otherRef.m_ptr; // Implicit conversion from otherRefType to refType should occur + wxCFRetain(otherRef.get()); + wxCFRelease(m_ptr); + m_ptr = otherRef.get(); // Implicit conversion from otherRefType to refType should occur return *this; } @@ -160,8 +283,7 @@ public: */ void reset() { - if(m_ptr != NULL) - CFRelease(m_ptr); + wxCFRelease(m_ptr); m_ptr = NULL; } @@ -178,8 +300,7 @@ public: template void reset(otherType* p) { - if(m_ptr != NULL) - CFRelease(m_ptr); + wxCFRelease(m_ptr); m_ptr = p; // Automatic conversion should occur } protected: @@ -199,25 +320,30 @@ protected: template inline wxCFRef wxCFRefFromGet(Type *p) { - return wxCFRef( (p!=NULL) ? (Type*)CFRetain(p) : p ); + return wxCFRef(wxCFRetain(p)); } /*! @function static_cfref_cast - @abstract Works like static_cast but from one wxCFRef to another + @abstract Works like static_cast but with a wxCFRef as the argument. @param refType Template parameter. The destination raw pointer type @param otherRef Normal parameter. The source wxCFRef<> object. - @discussion This is modeled after shared_ptr's static_pointer_cast. Just as wxCFRef is + @discussion This is intended to be a clever way to make static_cast work while allowing + the return value to be converted to either a strong ref or a raw pointer + while ensuring that the retain count is updated appropriately. + + This is modeled after shared_ptr's static_pointer_cast. Just as wxCFRef is parameterized on a pointer to an opaque type so is this class. Note that this differs from shared_ptr which is parameterized on the pointee type. + FIXME: Anybody got a better name? */ template -inline wxCFRef static_cfref_cast(const wxCFRef &otherRef); +inline wxCFWeakRef static_cfref_cast(const wxCFRef &otherRef); template -inline wxCFRef static_cfref_cast(const wxCFRef &otherRef) +inline wxCFWeakRef static_cfref_cast(const wxCFRef &otherRef) { - return wxCFRef(static_cast(CFRetain(otherRef.get()))); + return wxCFWeakRef(static_cast(otherRef.get())); } /*! @function CFRelease