// Name: wx/mac/corefoundation/cfref.h
// Purpose: wxCFRef template class
// Author: David Elliott <dfe@cox.net>
-// Modified by:
+// Modified by: Stefan Csomor
// Created: 2007/05/10
// RCS-ID: $Id$
-// Copyright: (c) 2007 David Elliott <dfe@cox.net>
+// Copyright: (c) 2007 David Elliott <dfe@cox.net>, Stefan Csomor
// Licence: wxWindows licence
// Notes: See http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/index.html
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MAC_COREFOUNDATION_CFREF_H__
#define _WX_MAC_COREFOUNDATION_CFREF_H__
-#include <CoreFoundation/CFBase.h>
+// #include <CoreFoundation/CFBase.h>
+/* 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 <class Type>
+inline void wxCFRelease(Type *r)
+{
+ if ( r != NULL )
+ ::CFRelease((CFTypeRef)r);
+}
+
+/*! @function wxCFRetain
+ @abstract A typesafe CFRetain variant that checks for NULL.
+*/
+template <class Type>
+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 refType>
+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 refType>
-class wxCFRef
+class wxCFWeakRef
{
- // Declare wxCFRef<otherRefType> as a friend so that the conversion constructor can access m_ptr directly
+ template <class refTypeA, class otherRefType>
+ friend wxCFWeakRef<refTypeA> static_cfref_cast(const wxCFRef<otherRefType> &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 <class otherRefType>
- friend class wxCFRef;
+ wxCFWeakRef(const wxCFWeakRef<otherRefType>& 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 <class otherRefType>
+ wxCFWeakRef(const wxCFRef<otherRefType>& 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 <class otherType>
+ 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 refType>
+class wxCFRef
+{
public:
/*! @method wxCFRef
@abstract Creates a NULL reference
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
*/
template <class otherRefType>
wxCFRef(const wxCFRef<otherRefType>& 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 <class otherRefType>
+ wxCFRef(const wxCFWeakRef<otherRefType>& otherRef)
+ : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur
+ {}
/*! @method ~wxCFRef
@abstract Releases (potentially shared) ownership of the ref.
*/
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;
}
template <class otherRefType>
wxCFRef& operator=(const wxCFRef<otherRefType>& 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;
}
*/
void reset()
{
- if(m_ptr != NULL)
- CFRelease(m_ptr);
+ wxCFRelease(m_ptr);
m_ptr = NULL;
}
template <class otherType>
void reset(otherType* p)
{
- if(m_ptr != NULL)
- CFRelease(m_ptr);
+ wxCFRelease(m_ptr);
m_ptr = p; // Automatic conversion should occur
}
protected:
template <typename Type>
inline wxCFRef<Type*> wxCFRefFromGet(Type *p)
{
- return wxCFRef<Type*>( (p!=NULL) ? (Type*)CFRetain(p) : p );
+ return wxCFRef<Type*>(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 <class refType, class otherRefType>
-inline wxCFRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef);
+inline wxCFWeakRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef);
template <class refType, class otherRefType>
-inline wxCFRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef)
+inline wxCFWeakRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef)
{
- return wxCFRef<refType>(static_cast<refType>(CFRetain(otherRef.get())));
+ return wxCFWeakRef<refType>(static_cast<refType>(otherRef.get()));
}
/*! @function CFRelease