hxsmartptr.h
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 17k
Category:

Symbian

Development Platform:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */
  35. /*!
  36.   @header hxsmartptr.h
  37.   
  38.   @abstract Macro implementation of smart pointers to COM interfaces
  39.             Based on pnmiscpubsmartptr.h
  40.  
  41.   @discussion
  42.   A SmartPointer is a class that contains a pointer, but acts like it 
  43.   <em>is</em> the contained pointer.  When used it helps enforce correct usage 
  44.   of the pointer it contains.  In this case it provides the following 
  45.   safeguards:<ul>
  46.       <li>ASSERT if the contained pointer is NULL when you attempt to 
  47.   use it.
  48.       <li>ASSERT if you attempt to replace a valid pointer without 
  49.   releasing it.
  50.       <li>Automatically AddRef() a pointer during assignment.
  51.       <li>Automatically QI() an incoming pointer to the correct type 
  52.   during assignment.
  53.       <li>Automatically Release() an existing pointer during assignment.
  54.       <li>Automatically Release() an existing pointer during destruction.
  55.        </ul>
  56.  
  57.   SmartPointers also simplify usage. Example:
  58.  
  59.     <pre><code>
  60.     HX_SMART_POINTER_INLINE( SPIHXBuffer, IHXBuffer );
  61.     ReadDone(HX_RESULT status, IUnknown* pbufData)
  62.     {
  63.         SPIHXBufferPtr spBufData = pbufData;
  64.         if(spBufData.IsValid())
  65.         {
  66.             cout << spBufData->GetBuffer() << endl;
  67.         }
  68.     }
  69.     </code></pre>
  70.   This example has no memory leaks.  In the Assignment the IUnknown 
  71.   pointer is QI'd for the IHXBuffer.  If the QI had failed, then 
  72.   the IsValid test would fail too.  Even if the IsValid Test was 
  73.   omitted, spbufData->GetBuffer() would cause an assertion if 
  74.   the QI had failed.
  75.  
  76.    Usage Tips:
  77.  
  78.   Cannot use SmartPointers as List elements.
  79.  
  80.    Note that there are specific macros for creating smart pointers to 
  81.    IUnknowns - plugging IUnknown into the standard smart pointer 
  82.    generation macros will cause compile errors.
  83.  
  84.    The interface has been cut down to a minimum. In particular, the 
  85.    automatic conversion operators have been removed to avoid the 
  86.    possibility of unexpected conversions happening automatically. It 
  87.    is still possible to get to the raw pointer if it is necessary.
  88.  
  89.  */
  90. /*!
  91.     @class SPIUnknown
  92.     @description A smart pointer to an IUnknown. This will always contain the unique IUnknown 
  93.       - i.e. it will QI any pointer passed to it (including IUnknown pointers) to make sure it gets 
  94.       the unique IUnknown.
  95. */
  96. /*!
  97.     @class SPCIUnknown
  98.     @description A const smart pointer to an IUnknown. This will always contain the unique IUnknown 
  99.       - i.e. it will QI any pointer passed to it (including IUnknown pointers) to make sure it gets 
  100.       the unique IUnknown.
  101. */
  102. /*!
  103.     @function CLASS_NAME()
  104. */
  105. /*!
  106.     @function CLASS_NAME( const CLASS_NAME& rspact )
  107. */
  108. /*!
  109.     @function CLASS_NAME(INTERFACE* pact)
  110. */
  111. /*!
  112.     @function ~CLASS_NAME()
  113. */
  114. /*!
  115.     @function CLASS_NAME(IHXCommonClassFactory* pIObjectSource, REFCLSID clsid, HX_RESULT* pResult = NULL )
  116.     @description Create an object from a factory and attempt to assign it 
  117.       to this smart pointer. If the created object supports the interface 
  118.       this smart pointer refers, the smart pointer will point to that object. 
  119.       If the created object does not support the interface, the smart pointer 
  120.       will end up as NULL and the created object will be immediately destroyed.
  121.     @param pIObjectSource The class factory to use
  122.     @param clsid The clsid of the object to create
  123.     @param pResult The result of the CreateInstance call - if this parameter 
  124.       is NULL the result will not be returned.
  125. */
  126. /*!
  127.     @function INTERFACE* operator -> () const
  128. */
  129. /*!
  130.     @function INTERFACE& operator * () const
  131. */
  132. /*!
  133.     @function CLASS_NAME& operator =( const CLASS_NAME& rspact )
  134. */
  135. /*!
  136.     @function CLASS_NAME& operator =( INTERFACE* pNew )
  137. */
  138. /*!
  139.     @function BOOL IsValid() const
  140. */
  141. /*!
  142.     @function INTERFACE* Ptr() const
  143.     @description Returns a non-addrefed version of the internal 
  144.       pointer. This is designed to be used as an easy way of 
  145.       passing the pointer to functions that take an unadorned 
  146.       pointer. If the pointer is assigned to a local variable, 
  147.       please bear in mind that it is not addrefed and should 
  148.       be treated accordingly. The best way to get an AddReffed 
  149.       pointer assigned to a local variable is to use the AsPtr 
  150.       method.
  151. */
  152. /*!
  153.     @function AsPtr( INTERFACE*  ) const
  154.     @description Returns an addrefed version of the internal 
  155.       pointer. Onlu available on non-const smart pointers (if
  156.       this was available for a const smart pointer it would 
  157.       have to return a const pointer which then couldn't be 
  158.       released ).
  159. */
  160. /*!
  161.     @function void AsUnknown( IUnknown** ppIUnknown ) const
  162.     @description Returns an addrefed version of the pointer as an 
  163.       IUnknown*.
  164. */
  165. /*!
  166.      @function Query( IUnknown* pIUnk )
  167.      @description If possible, set the value of this smart pointer to the
  168. given pointer. The value of this smart pointer will only be changed if the
  169. supplied pointer is non-NULL and it supports the interface corresponding to
  170. this smart pointer. If either of these conditions is not true the value of
  171. the smart pointer will be unchanged.
  172.      @param pIUnk The pointer to try and assign to this.
  173.      @result There are three possible results:
  174.          1. If the pointer passed in was non-NULL and the object supported the
  175.     appropriate interface, a SUCCEEDED result will be returned (corresponding
  176.     to the result of the internal QI).
  177.          2. If the pointer passed in was non_NULL but the object did not 
  178.     support the appropriate interface, a FAILED result will be returned 
  179.     (corresponding to the result of the internal QI).
  180.          3. If the pointer passed in was NULL, HXR_INVALID_PARAMETER will be returned.
  181. */
  182. /*!
  183.      @function Clear()
  184.      @description Releases the smart pointers reference to the underlying pointer and 
  185.        set the smart pointer to NULL.
  186. */
  187. /*!
  188.      @function AsInOutParam()
  189.      @description Clears the smart pointer, then returns a pointer to the underlying 
  190.        pointer. This is suitable for passing to functions which pass back an AddReffed 
  191.        pointer as output. E.g.
  192.       void SomeFunction( IHXSomeInterface** ppOutput );
  193.       SPIHXSomeInterface spI;
  194.       SomeFunction( spi>AsInOutParam() );
  195. */
  196. #ifndef _HXSMARTPTR_H_
  197. #define _HXSMARTPTR_H_
  198. #include "hxassert.h"
  199. #include "hxcom.h"
  200. #include "hxccf.h"
  201. /*!
  202.     @defined HX_SMART_POINTER_INLINE
  203.     @abstract 
  204. Declare a smart pointer of name CLASS_NAME which points to an 
  205. interface INTERFACE. Inline definitions of all functions.
  206. */
  207. #define HX_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE )
  208. HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, HX_PRIVATE_BLANK, HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, HX_PRIVATE_BLANK ) )
  209. /*!
  210.     @defined HX_CONST_SMART_POINTER_INLINE
  211.     @abstract 
  212. Declare a const smart pointer of name CLASS_NAME which points to an 
  213. interface INTERFACE. Inline definitions of all functions.
  214. */
  215. #define HX_CONST_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE )
  216. HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, const, HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, const ) )
  217. /*!
  218.     @defined HX_IUNKNOWN_SMART_POINTER_INLINE
  219.     @abstract 
  220. Declare a smart pointer of name CLASS_NAME which points to an 
  221. IUnknown interface. Inline definitions of all functions.
  222. */
  223. #define HX_IUNKNOWN_SMART_POINTER_INLINE( CLASS_NAME )
  224. HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, IUnknown, HX_PRIVATE_BLANK, HX_PRIVATE_BLANK )
  225. /*!
  226.     @defined HX_IUNKNOWN_CONST_SMART_POINTER_INLINE
  227.     @abstract 
  228. Declare a const smart pointer of name CLASS_NAME which points to an 
  229. IUnknown interface. Inline definitions of all functions.
  230. */
  231. #define HX_IUNKNOWN_CONST_SMART_POINTER_INLINE( CLASS_NAME )
  232. HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, IUnknown, const, HX_PRIVATE_BLANK )
  233. // ---------------------------------------------------------------------
  234. // The macros below here should not be used directly. They might 
  235. // change in future implementations
  236. // ---------------------------------------------------------------------
  237. // The IUnknown functions macros have been included 
  238. // to reduce code duplication. If we just attempt to use the normal 
  239. // macros for creating an IUnknown smart pointer we end up with compile 
  240. // errors because the copy constructor and assignment ops are duplicated.
  241. // The HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS macro separates out a copy 
  242. // constructor / assignment op that are needed in the non-IUnknown versions 
  243. // but would cause errors in the IUnknown versions.
  244. #define HX_PRIVATE_NON_IUNKNOWN_FUNCTIONS( CLASS_NAME, INTERFACE, QUALIFIERS )
  245.     CLASS_NAME(INTERFACE QUALIFIERS* pact)
  246.     : pActual(NULL)
  247.     {
  248. if( pact )
  249. {
  250.     pActual = (INTERFACE*) pact;
  251.     pActual->AddRef();
  252. }
  253.     }
  254.     CLASS_NAME& operator =( INTERFACE QUALIFIERS* pNew )
  255.     {
  256. if( pNew != pActual )
  257. {
  258.     INTERFACE* pTemp = pActual;
  259.     pActual = (INTERFACE*) pNew;
  260.     if( pActual )
  261.     {
  262. pActual->AddRef();
  263.     }
  264.     HX_RELEASE( pTemp );
  265. }
  266. return *this;
  267.     }
  268. #define HX_PRIVATE_SMART_POINTER_INLINE( CLASS_NAME, INTERFACE, QUALIFIERS, NON_IUNKNOWN_DEFINITIONS )
  269. class CLASS_NAME
  270. {
  271. public:
  272.     CLASS_NAME()
  273. : pActual(NULL)
  274.     {}
  275.     CLASS_NAME( const CLASS_NAME& rspact )
  276.     : pActual(NULL)
  277.     {
  278. if( rspact.pActual )
  279. {
  280.     pActual = rspact.pActual;
  281.     pActual->AddRef();
  282. }
  283.     }
  284.     CLASS_NAME(IUnknown QUALIFIERS* punk)
  285.     : pActual(NULL)
  286.     {
  287.         if(punk)
  288.     ((IUnknown*) punk)->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
  289.     }
  290.     CLASS_NAME& operator =( IUnknown QUALIFIERS* punkNew )
  291.     {
  292. if( punkNew != pActual )
  293. {
  294.     INTERFACE* pTemp = pActual;
  295.     if(punkNew)
  296.     {
  297. ((IUnknown*) punkNew)->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
  298.     }
  299.     else
  300.     {
  301. pActual = NULL;
  302.     }
  303.     HX_RELEASE( pTemp );
  304. }
  305. return *this;
  306.     }
  307.     CLASS_NAME( IHXCommonClassFactory* pIObjectSource, REFCLSID clsid, HX_RESULT* pResult = NULL ) 
  308.     : pActual(NULL)
  309.     {
  310. HX_ASSERT(pIObjectSource);
  311. IUnknown* pIUnk = NULL;
  312. HX_RESULT result = pIObjectSource->CreateInstance( clsid, (void**)&pIUnk );
  313. if (SUCCEEDED(result))
  314. {
  315.     HX_ASSERT(pIUnk);
  316.     result = pIUnk->QueryInterface( IID_##INTERFACE, ( void** )( &pActual ) );
  317.     pIUnk->Release();
  318. }
  319. if( pResult )
  320. {
  321.     *pResult = result;
  322. }
  323.     }
  324.     NON_IUNKNOWN_DEFINITIONS
  325.     ~CLASS_NAME()
  326.     { HX_RELEASE (pActual); }
  327.     class INTERFACE##_InternalSP : public INTERFACE
  328.     {
  329.     private:
  330. virtual ULONG32 STDMETHODCALLTYPE AddRef () PURE;
  331. virtual ULONG32 STDMETHODCALLTYPE Release () PURE;
  332.     };
  333.     INTERFACE##_InternalSP QUALIFIERS* operator -> () const
  334.     {HX_ASSERT(pActual);return (INTERFACE##_InternalSP*) pActual;}
  335.     INTERFACE##_InternalSP QUALIFIERS& operator * () const
  336.     {HX_ASSERT(pActual);return *((INTERFACE##_InternalSP*) pActual);}
  337.     CLASS_NAME& operator =( const CLASS_NAME& rspact )
  338.     {*this = rspact.pActual; return *this;}
  339.     HX_RESULT Query(IUnknown QUALIFIERS* punkNew)
  340.     {
  341. HX_RESULT result = HXR_INVALID_PARAMETER;
  342. if( punkNew )
  343. {
  344.     result = HXR_OK;
  345.     if( punkNew != pActual )
  346.     {
  347. INTERFACE* pTemp = NULL;
  348. result = ((IUnknown*) punkNew)->QueryInterface( IID_##INTERFACE, ( void** )( &pTemp ) );
  349. if( SUCCEEDED( result ) )
  350. {
  351.     HX_RELEASE( pActual );
  352.     pActual = pTemp;
  353. }
  354.     }
  355. }
  356. return result;
  357.     }
  358.     BOOL IsValid() const
  359.     {return pActual!=NULL;}
  360.     INTERFACE** AsInOutParam () 
  361.     { HX_RELEASE (pActual); return &pActual; }
  362.     INTERFACE QUALIFIERS* Ptr() const
  363.     {return pActual;}
  364.     void AsPtr( INTERFACE QUALIFIERS** ppActual ) const
  365.     {
  366. HX_ASSERT(pActual);
  367. pActual->AddRef ();
  368. *ppActual = pActual;
  369.     }
  370.     void AsUnknown( IUnknown QUALIFIERS** ppIUnknown ) const
  371.     {
  372. HX_ASSERT(pActual);
  373. pActual->QueryInterface
  374. (
  375.     IID_IUnknown,
  376.     ( void** )ppIUnknown
  377. );
  378.     }
  379.     void Clear ()
  380.     { HX_RELEASE (pActual); }
  381. private:
  382.     INTERFACE*     pActual;
  383. }
  384. #define HX_PRIVATE_BLANK
  385. HX_IUNKNOWN_SMART_POINTER_INLINE( SPIUnknown );
  386. HX_IUNKNOWN_CONST_SMART_POINTER_INLINE( SPCIUnknown );
  387. // Since we are guaranteed that SPIUnknown and SPCIUnknown will be storing 
  388. // the unique IUnknown pointer we can just compare the results of the Ptr function.
  389. inline BOOL operator ==( const SPIUnknown& sp1, const SPIUnknown& sp2 )
  390. {
  391.     return sp1.Ptr() == sp2.Ptr();
  392. }
  393. inline BOOL operator ==( const SPCIUnknown& spc1, const SPCIUnknown& spc2 )
  394. {
  395.     return spc1.Ptr() == spc2.Ptr();
  396. }
  397. /* These cannot be activated without letting everybody know. Some code might
  398.  fail to compile: 
  399.   IRCAClickable* p = 0;
  400.   if (p == SPIUnknown(p))  //is ambigous
  401.   { ... }
  402.  
  403.  
  404. inline BOOL operator ==( const SPIUnknown& sp1, const SPCIUnknown& spc2 )
  405. {
  406.     return sp1.Ptr() == spc2.Ptr();
  407. }
  408. inline BOOL operator ==( const SPCIUnknown& spc1, const SPIUnknown& sp2 )
  409. {
  410.     return spc1.Ptr() == sp2.Ptr();
  411. }
  412. */
  413. inline BOOL operator !=( const SPIUnknown& sp1, const SPIUnknown& sp2 )
  414. {
  415.     return ! ( sp1 == sp2 );
  416. }
  417. inline BOOL operator !=( const SPCIUnknown& spc1, const SPCIUnknown& spc2 )
  418. {
  419.     return ! ( spc1 == spc2 );
  420. }
  421. /*
  422. inline BOOL operator !=( const SPIUnknown& sp1, const SPCIUnknown& spc2 )
  423. {
  424.     return ! ( sp1 == spc2 );
  425. }
  426. inline BOOL operator !=( const SPCIUnknown& spc1, const SPIUnknown& sp2 )
  427. {
  428.     return ! ( spc1 == sp2 );
  429. }
  430. */
  431. #endif // _HXSMARTPTR_H_