hxsmartptr.h
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:17k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxsmartptr.h,v 1.3.18.3 2004/07/09 01:45:13 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /*!
- @header hxsmartptr.h
-
- @abstract Macro implementation of smart pointers to COM interfaces
- Based on pnmiscpubsmartptr.h
-
- @discussion
- A SmartPointer is a class that contains a pointer, but acts like it
- <em>is</em> the contained pointer. When used it helps enforce correct usage
- of the pointer it contains. In this case it provides the following
- safeguards:<ul>
- <li>ASSERT if the contained pointer is NULL when you attempt to
- use it.
- <li>ASSERT if you attempt to replace a valid pointer without
- releasing it.
- <li>Automatically AddRef() a pointer during assignment.
- <li>Automatically QI() an incoming pointer to the correct type
- during assignment.
- <li>Automatically Release() an existing pointer during assignment.
- <li>Automatically Release() an existing pointer during destruction.
- </ul>
-
- SmartPointers also simplify usage. Example:
-
- <pre><code>
- HX_SMART_POINTER_INLINE( SPIHXBuffer, IHXBuffer );
- ReadDone(HX_RESULT status, IUnknown* pbufData)
- {
- SPIHXBufferPtr spBufData = pbufData;
- if(spBufData.IsValid())
- {
- cout << spBufData->GetBuffer() << endl;
- }
- }
- </code></pre>
- This example has no memory leaks. In the Assignment the IUnknown
- pointer is QI'd for the IHXBuffer. If the QI had failed, then
- the IsValid test would fail too. Even if the IsValid Test was
- omitted, spbufData->GetBuffer() would cause an assertion if
- the QI had failed.
-
- Usage Tips:
-
- Cannot use SmartPointers as List elements.
-
- Note that there are specific macros for creating smart pointers to
- IUnknowns - plugging IUnknown into the standard smart pointer
- generation macros will cause compile errors.
-
- The interface has been cut down to a minimum. In particular, the
- automatic conversion operators have been removed to avoid the
- possibility of unexpected conversions happening automatically. It
- is still possible to get to the raw pointer if it is necessary.
-
- */
- /*!
- @class SPIUnknown
- @description A smart pointer to an IUnknown. This will always contain the unique IUnknown
- - i.e. it will QI any pointer passed to it (including IUnknown pointers) to make sure it gets
- the unique IUnknown.
- */
- /*!
- @class SPCIUnknown
- @description A const smart pointer to an IUnknown. This will always contain the unique IUnknown
- - i.e. it will QI any pointer passed to it (including IUnknown pointers) to make sure it gets
- the unique IUnknown.
- */
- /*!
- @function CLASS_NAME()
- */
- /*!
- @function CLASS_NAME( const CLASS_NAME& rspact )
- */
- /*!
- @function CLASS_NAME(INTERFACE* pact)
- */
- /*!
- @function ~CLASS_NAME()
- */
- /*!
- @function CLASS_NAME(IHXCommonClassFactory* pIObjectSource, REFCLSID clsid, HX_RESULT* pResult = NULL )
- @description Create an object from a factory and attempt to assign it
- to this smart pointer. If the created object supports the interface
- this smart pointer refers, the smart pointer will point to that object.
- If the created object does not support the interface, the smart pointer
- will end up as NULL and the created object will be immediately destroyed.
- @param pIObjectSource The class factory to use
- @param clsid The clsid of the object to create
- @param pResult The result of the CreateInstance call - if this parameter
- is NULL the result will not be returned.
- */
- /*!
- @function INTERFACE* operator -> () const
- */
- /*!
- @function INTERFACE& operator * () const
- */
- /*!
- @function CLASS_NAME& operator =( const CLASS_NAME& rspact )
- */
- /*!
- @function CLASS_NAME& operator =( INTERFACE* pNew )
- */
- /*!
- @function BOOL IsValid() const
- */
- /*!
- @function INTERFACE* Ptr() const
- @description Returns a non-addrefed version of the internal
- pointer. This is designed to be used as an easy way of
- passing the pointer to functions that take an unadorned
- pointer. If the pointer is assigned to a local variable,
- please bear in mind that it is not addrefed and should
- be treated accordingly. The best way to get an AddReffed
- pointer assigned to a local variable is to use the AsPtr
- method.
- */
- /*!
- @function AsPtr( INTERFACE* ) const
- @description Returns an addrefed version of the internal
- pointer. Onlu available on non-const smart pointers (if
- this was available for a const smart pointer it would
- have to return a const pointer which then couldn't be
- released ).
- */
- /*!
- @function void AsUnknown( IUnknown** ppIUnknown ) const
- @description Returns an addrefed version of the pointer as an
- IUnknown*.
- */
- /*!
- @function Query( IUnknown* pIUnk )
- @description If possible, set the value of this smart pointer to the
- given pointer. The value of this smart pointer will only be changed if the
- supplied pointer is non-NULL and it supports the interface corresponding to
- this smart pointer. If either of these conditions is not true the value of
- the smart pointer will be unchanged.
- @param pIUnk The pointer to try and assign to this.
- @result There are three possible results:
- 1. If the pointer passed in was non-NULL and the object supported the
- appropriate interface, a SUCCEEDED result will be returned (corresponding
- to the result of the internal QI).
- 2. If the pointer passed in was non_NULL but the object did not
- support the appropriate interface, a FAILED result will be returned
- (corresponding to the result of the internal QI).
- 3. If the pointer passed in was NULL, HXR_INVALID_PARAMETER will be returned.
- */
- /*!
- @function Clear()
- @description Releases the smart pointers reference to the underlying pointer and
- set the smart pointer to NULL.
- */
- /*!
- @function AsInOutParam()
- @description Clears the smart pointer, then returns a pointer to the underlying
- pointer. This is suitable for passing to functions which pass back an AddReffed
- pointer as output. E.g.
- void SomeFunction( IHXSomeInterface** ppOutput );
- SPIHXSomeInterface spI;
- SomeFunction( spi>AsInOutParam() );
- */
- #ifndef _HXSMARTPTR_H_
- #define _HXSMARTPTR_H_
- #include "hxassert.h"
- #include "hxcom.h"
- #include "hxccf.h"
- /*!
- @defined HX_SMART_POINTER_INLINE
- @abstract
- Declare a smart pointer of name CLASS_NAME which points to an
- interface INTERFACE. Inline definitions of all functions.
- */
- #define HX_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE )
- HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, HX_PRIVATE_BLANK, HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, HX_PRIVATE_BLANK ) )
- /*!
- @defined HX_CONST_SMART_POINTER_INLINE
- @abstract
- Declare a const smart pointer of name CLASS_NAME which points to an
- interface INTERFACE. Inline definitions of all functions.
- */
- #define HX_CONST_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE )
- HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, const, HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, const ) )
- /*!
- @defined HX_IUNKNOWN_SMART_POINTER_INLINE
- @abstract
- Declare a smart pointer of name CLASS_NAME which points to an
- IUnknown interface. Inline definitions of all functions.
- */
- #define HX_IUNKNOWN_SMART_POINTER_INLINE( CLASS_NAME )
- HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, IUnknown, HX_PRIVATE_BLANK, HX_PRIVATE_BLANK )
- /*!
- @defined HX_IUNKNOWN_CONST_SMART_POINTER_INLINE
- @abstract
- Declare a const smart pointer of name CLASS_NAME which points to an
- IUnknown interface. Inline definitions of all functions.
- */
- #define HX_IUNKNOWN_CONST_SMART_POINTER_INLINE( CLASS_NAME )
- HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, IUnknown, const, HX_PRIVATE_BLANK )
- // ---------------------------------------------------------------------
- // The macros below here should not be used directly. They might
- // change in future implementations
- // ---------------------------------------------------------------------
- // The IUnknown functions macros have been included
- // to reduce code duplication. If we just attempt to use the normal
- // macros for creating an IUnknown smart pointer we end up with compile
- // errors because the copy constructor and assignment ops are duplicated.
- // The HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS macro separates out a copy
- // constructor / assignment op that are needed in the non-IUnknown versions
- // but would cause errors in the IUnknown versions.
- #define HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, QUALIFIERS )
- CLASS_NAME(INTERFACE QUALIFIERS* pact)
- : pActual(NULL)
- {
- if( pact )
- {
- pActual = (INTERFACE*) pact;
- pActual->AddRef();
- }
- }
- CLASS_NAME& operator =( INTERFACE QUALIFIERS* pNew )
- {
- if( pNew != pActual )
- {
- INTERFACE* pTemp = pActual;
- pActual = (INTERFACE*) pNew;
- if( pActual )
- {
- pActual->AddRef();
- }
- HX_RELEASE( pTemp );
- }
- return *this;
- }
- #define HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, QUALIFIERS, NON_IUNKNOWN_DEFINITIONS )
-
- class CLASS_NAME
- {
- public:
- CLASS_NAME()
- : pActual(NULL)
- {}
-
- CLASS_NAME( const CLASS_NAME& rspact )
- : pActual(NULL)
- {
- if( rspact.pActual )
- {
- pActual = rspact.pActual;
- pActual->AddRef();
- }
- }
-
- CLASS_NAME(IUnknown QUALIFIERS* punk)
- : pActual(NULL)
- {
- if(punk)
- ((IUnknown*) punk)->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
- }
- CLASS_NAME& operator =( IUnknown QUALIFIERS* punkNew )
- {
- if( punkNew != pActual )
- {
- INTERFACE* pTemp = pActual;
- if(punkNew)
- {
- ((IUnknown*) punkNew)->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
- }
- else
- {
- pActual = NULL;
- }
- HX_RELEASE( pTemp );
- }
- return *this;
- }
-
- CLASS_NAME( IHXCommonClassFactory* pIObjectSource, REFCLSID clsid, HX_RESULT* pResult = NULL )
- : pActual(NULL)
- {
- HX_ASSERT(pIObjectSource);
- IUnknown* pIUnk = NULL;
- HX_RESULT result = pIObjectSource->CreateInstance( clsid, (void**)&pIUnk );
- if (SUCCEEDED(result))
- {
- HX_ASSERT(pIUnk);
- result = pIUnk->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
- pIUnk->Release();
- }
- if( pResult )
- {
- *pResult = result;
- }
- }
-
- NON_IUNKNOWN_DEFINITIONS
-
- ~CLASS_NAME()
- { HX_RELEASE (pActual); }
-
- class INTERFACE##_InternalSP : public INTERFACE
- {
- private:
- virtual ULONG32 STDMETHODCALLTYPE AddRef () PURE;
- virtual ULONG32 STDMETHODCALLTYPE Release () PURE;
- };
-
- INTERFACE##_InternalSP QUALIFIERS* operator -> () const
- {HX_ASSERT(pActual);return (INTERFACE##_InternalSP*) pActual;}
-
- INTERFACE##_InternalSP QUALIFIERS& operator * () const
- {HX_ASSERT(pActual);return *((INTERFACE##_InternalSP*) pActual);}
-
- CLASS_NAME& operator =( const CLASS_NAME& rspact )
- {*this = rspact.pActual; return *this;}
-
-
-
- HX_RESULT Query(IUnknown QUALIFIERS* punkNew)
- {
- HX_RESULT result = HXR_INVALID_PARAMETER;
- if( punkNew )
- {
- result = HXR_OK;
- if( punkNew != pActual )
- {
- INTERFACE* pTemp = NULL;
- result = ((IUnknown*) punkNew)->QueryInterface( IID_##INTERFACE, ( void** )( &pTemp ) );
- if( SUCCEEDED( result ) )
- {
- HX_RELEASE( pActual );
- pActual = pTemp;
- }
- }
- }
- return result;
- }
-
- BOOL IsValid() const
- {return pActual!=NULL;}
-
- INTERFACE** AsInOutParam ()
- { HX_RELEASE (pActual); return &pActual; }
-
- INTERFACE QUALIFIERS* Ptr() const
- {return pActual;}
-
- void AsPtr( INTERFACE QUALIFIERS** ppActual ) const
- {
- HX_ASSERT(pActual);
- pActual->AddRef ();
- *ppActual = pActual;
- }
-
- void AsUnknown( IUnknown QUALIFIERS** ppIUnknown ) const
- {
- HX_ASSERT(pActual);
- pActual->QueryInterface
- (
- IID_IUnknown,
- ( void** )ppIUnknown
- );
- }
-
- void Clear ()
- { HX_RELEASE (pActual); }
-
- private:
- INTERFACE* pActual;
- }
- #define HX_PRIVATE_BLANK
- HX_IUNKNOWN_SMART_POINTER_INLINE( SPIUnknown );
- HX_IUNKNOWN_CONST_SMART_POINTER_INLINE( SPCIUnknown );
- // Since we are guaranteed that SPIUnknown and SPCIUnknown will be storing
- // the unique IUnknown pointer we can just compare the results of the Ptr function.
- inline BOOL operator ==( const SPIUnknown& sp1, const SPIUnknown& sp2 )
- {
- return sp1.Ptr() == sp2.Ptr();
- }
- inline BOOL operator ==( const SPCIUnknown& spc1, const SPCIUnknown& spc2 )
- {
- return spc1.Ptr() == spc2.Ptr();
- }
- /* These cannot be activated without letting everybody know. Some code might
- fail to compile:
- IRCAClickable* p = 0;
- if (p == SPIUnknown(p)) //is ambigous
- { ... }
-
-
- inline BOOL operator ==( const SPIUnknown& sp1, const SPCIUnknown& spc2 )
- {
- return sp1.Ptr() == spc2.Ptr();
- }
- inline BOOL operator ==( const SPCIUnknown& spc1, const SPIUnknown& sp2 )
- {
- return spc1.Ptr() == sp2.Ptr();
- }
- */
- inline BOOL operator !=( const SPIUnknown& sp1, const SPIUnknown& sp2 )
- {
- return ! ( sp1 == sp2 );
- }
- inline BOOL operator !=( const SPCIUnknown& spc1, const SPCIUnknown& spc2 )
- {
- return ! ( spc1 == spc2 );
- }
- /*
- inline BOOL operator !=( const SPIUnknown& sp1, const SPCIUnknown& spc2 )
- {
- return ! ( sp1 == spc2 );
- }
- inline BOOL operator !=( const SPCIUnknown& spc1, const SPIUnknown& sp2 )
- {
- return ! ( spc1 == sp2 );
- }
- */
- #endif // _HXSMARTPTR_H_