]> git.saurik.com Git - wxWidgets.git/commitdiff
Added cfref.h containing wxCFRef templated CF ref holding class and related functions.
authorDavid Elliott <dfe@tgwbd.org>
Sat, 12 May 2007 18:55:58 +0000 (18:55 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Sat, 12 May 2007 18:55:58 +0000 (18:55 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45998 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/mac/corefoundation/cfref.h [new file with mode: 0644]

diff --git a/include/wx/mac/corefoundation/cfref.h b/include/wx/mac/corefoundation/cfref.h
new file mode 100644 (file)
index 0000000..29485f4
--- /dev/null
@@ -0,0 +1,258 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/mac/corefoundation/cfref.h
+// Purpose:     wxCFRef template class
+// Author:      David Elliott <dfe@cox.net>
+// Modified by: 
+// Created:     2007/05/10
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 David Elliott <dfe@cox.net>
+// Licence:     wxWindows licence
+// Notes:       See http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/index.html
+/////////////////////////////////////////////////////////////////////////////
+/*! @header     wx/mac/corefoundation/cfref.h
+    @abstract   wxCFRef template class
+    @discussion FIXME: Convert doc tags to something less buggy with C++
+*/
+
+#ifndef _WX_MAC_COREFOUNDATION_CFREF_H__
+#define _WX_MAC_COREFOUNDATION_CFREF_H__
+
+#include <CoreFoundation/CFBase.h>
+
+/*! @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
+{
+    // Declare wxCFRef<otherRefType> as a friend so that the conversion constructor can access m_ptr directly
+    template <class otherRefType>
+    friend class wxCFRef;
+
+
+public:
+    /*! @method     wxCFRef
+        @abstract   Creates a NULL reference
+    */
+    wxCFRef()
+    :   m_ptr(NULL)
+    {}
+
+    /*! @method     wxCFRef
+        @abstract   Assumes ownership of p and creates a reference to it.
+        @templatefield otherType    Any type.
+        @param p        The raw pointer to assume ownership of.  May be NULL.
+        @discussion Like shared_ptr, it is assumed that the caller has a strong reference to p and intends
+                    to transfer ownership of that reference to this ref holder.  If the object comes from
+                    a Create or Copy method then this is the correct behavior.  If the object comes from
+                    a Get method then you must CFRetain it yourself before passing it to this constructor.
+                    A handy way to do this is to use the non-member wxCFRefFromGet factory funcion.
+                    This method is templated and takes an otherType *p.  This prevents implicit conversion
+                    using an operator refType() in a different ref-holding class type.
+    */
+    template <class otherType>
+    explicit wxCFRef(otherType *p)
+    :   m_ptr(p) // Implicit conversion from otherType* to refType should occur.
+    {}
+
+    /*! @method     wxCFRef
+        @abstract   Copies a ref holder of the same type
+        @param otherRef The other ref holder to copy.
+        @discussion Ownership will be shared by the original ref and the newly created ref. That is,
+                    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);
+    }
+
+    /*! @method     wxCFRef
+        @abstract   Copies a ref holder where its type can be converted to ours
+        @templatefield otherRefType     Any type held by another wxCFRef.
+        @param otherRef The other ref holder to copy.
+        @discussion Ownership will be shared by the original ref and the newly created ref. That is,
+                    the object will be explicitly retained by this new ref.
+    */
+    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);
+    }
+
+    /*! @method     ~wxCFRef
+        @abstract   Releases (potentially shared) ownership of the ref.
+        @discussion A ref holder instance is always assumed to have ownership so ownership is always
+                    released (CFRelease called) upon destruction.
+    */
+    ~wxCFRef()
+    {   reset(); }
+
+    /*! @method     operator=
+        @abstract   Assigns the other ref's pointer to us when the otherRef is the same type.
+        @param otherRef The other ref holder to copy.
+        @discussion The incoming pointer is retained, the original pointer is released, and this object
+                    is made to point to the new pointer.
+    */
+    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;
+        return *this;
+    }
+
+    /*! @method     operator=
+        @abstract   Assigns the other ref's pointer to us when the other ref can be converted to our type.
+        @templatefield otherRefType     Any type held by another wxCFRef
+        @param otherRef The other ref holder to copy.
+        @discussion The incoming pointer is retained, the original pointer is released, and this object
+                    is made to point to the new pointer.
+    */
+    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
+        return *this;
+    }
+
+    /*! @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; }
+
+#if 0
+    <   // HeaderDoc is retarded and thinks the GT from operator-> is part of a template param.
+        // So give it that < outside of a comment to fake it out. (if 0 is not a comment to HeaderDoc)
+#endif
+
+    /*! @method     operator-&gt;
+        @abstract   Implicit conversion to the underlying pointer type
+        @discussion This is nearly useless for CF types which are nearly always opaque
+    */
+    refType operator-> () const
+    {   return m_ptr; }
+
+    /*! @method     reset
+        @abstract   Nullifies the reference
+        @discussion Releases ownership (calls CFRelease) before nullifying the pointer.
+    */
+    void reset()
+    {
+        if(m_ptr != NULL)
+            CFRelease(m_ptr);
+        m_ptr = NULL;
+    }
+
+    /*! @method     reset
+        @abstract   Sets this to a new reference
+        @templatefield otherType    Any type.
+        @param p        The raw pointer to assume ownership of
+        @discussion The existing reference is released (like destruction).  It is assumed that the caller
+                    has a strong reference to the new p and intends to transfer ownership of that reference
+                    to this ref holder.  Take care to call CFRetain if you received the object from a Get method.
+                    This method is templated and takes an otherType *p.  This prevents implicit conversion
+                    using an operator refType() in a different ref-holding class type.
+    */
+    template <class otherType>
+    void reset(otherType* p)
+    {
+        if(m_ptr != NULL)
+            CFRelease(m_ptr);
+        m_ptr = p; // Automatic conversion should occur
+    }
+protected:
+    /*! @var m_ptr      The raw pointer.
+    */
+    refType m_ptr;
+};
+
+/*! @function   wxCFRefFromGet
+    @abstract   Factory function to create wxCFRef from a raw pointer obtained from a Get-rule function
+    @param  p           The pointer to retain and create a wxCFRef from.  May be NULL.
+    @discussion Unlike the wxCFRef raw pointer constructor, this function explicitly retains its
+                argument.  This can be used for functions such as CFDictionaryGetValue() or
+                CFAttributedStringGetString() which return a temporary reference (Get-rule functions).
+                FIXME: Anybody got a better name?
+*/
+template <typename Type>
+inline wxCFRef<Type*> wxCFRefFromGet(Type *p)
+{
+    return wxCFRef<Type*>( (p!=NULL) ? (Type*)CFRetain(p) : p );
+}
+
+/*! @function   static_cfref_cast
+    @abstract   Works like static_cast but from one wxCFRef to another
+    @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
+                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);
+
+template <class refType, class otherRefType>
+inline wxCFRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef)
+{
+    return wxCFRef<refType>(static_cast<refType>(CFRetain(otherRef.get())));
+}
+
+/*! @function   CFRelease
+    @abstract   Overloads CFRelease so that the user is warned of bad behavior.
+    @discussion It is rarely appropriate to retain or release a wxCFRef.  If one absolutely
+                must do it he can explicitly get() the raw pointer
+                Normally, this function is unimplemented resulting in a linker error if used.
+*/
+template <class T>
+inline void CFRelease(const wxCFRef<T*> & cfref) DEPRECATED_ATTRIBUTE;
+
+/*! @function   CFRetain
+    @abstract   Overloads CFRetain so that the user is warned of bad behavior.
+    @discussion It is rarely appropriate to retain or release a wxCFRef.  If one absolutely
+                must do it he can explicitly get() the raw pointer
+                Normally, this function is unimplemented resulting in a linker error if used.
+*/
+template <class T>
+inline void CFRetain(const wxCFRef<T*>& cfref) DEPRECATED_ATTRIBUTE;
+
+// Change the 0 to a 1 if you want the functions to work (no link errors)
+// Neither function will cause retain/release side-effects if implemented.
+#if 0
+template <class T>
+void CFRelease(const wxCFRef<T*> & cfref)
+{
+    CFRelease(cfref.get());
+}
+
+template <class T>
+void CFRetain(const wxCFRef<T*> & cfref)
+{
+    CFRetain(cfref.get());
+}
+#endif
+
+#endif //ndef _WX_MAC_COREFOUNDATION_CFREF_H__
+