/gecko_api/include/nsCOMPtr.h

http://firefox-mac-pdf.googlecode.com/ · C Header · 1694 lines · 1085 code · 256 blank · 353 comment · 45 complexity · d6c863a5a4a6d3c84ce2244326b520de MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is mozilla.org code.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications Corporation.
  19. * Portions created by the Initial Developer are Copyright (C) 1998
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Scott Collins <scc@mozilla.org> (original author)
  24. * L. David Baron <dbaron@dbaron.org>
  25. *
  26. * Alternatively, the contents of this file may be used under the terms of
  27. * either of the GNU General Public License Version 2 or later (the "GPL"),
  28. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29. * in which case the provisions of the GPL or the LGPL are applicable instead
  30. * of those above. If you wish to allow use of your version of this file only
  31. * under the terms of either the GPL or the LGPL, and not to allow others to
  32. * use your version of this file under the terms of the MPL, indicate your
  33. * decision by deleting the provisions above and replace them with the notice
  34. * and other provisions required by the GPL or the LGPL. If you do not delete
  35. * the provisions above, a recipient may use your version of this file under
  36. * the terms of any one of the MPL, the GPL or the LGPL.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. #ifndef nsCOMPtr_h___
  40. #define nsCOMPtr_h___
  41. /*
  42. Having problems?
  43. See the User Manual at:
  44. http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
  45. nsCOMPtr
  46. better than a raw pointer
  47. for owning objects
  48. -- scc
  49. */
  50. // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
  51. #ifndef nsDebug_h___
  52. #include "nsDebug.h"
  53. // for |NS_PRECONDITION|
  54. #endif
  55. #ifndef nsISupportsUtils_h__
  56. #include "nsISupportsUtils.h"
  57. // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
  58. #endif
  59. #ifndef nscore_h___
  60. #include "nscore.h"
  61. // for |NS_COM_GLUE|
  62. #endif
  63. /*
  64. WARNING:
  65. This file defines several macros for internal use only. These macros begin with the
  66. prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
  67. only for cross-platform compatibility, and are subject to change without notice.
  68. */
  69. #ifdef _MSC_VER
  70. #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  71. // under VC++, we win by inlining StartAssignment
  72. // Also under VC++, at the highest warning level, we are overwhelmed with warnings
  73. // about (unused) inline functions being removed. This is to be expected with
  74. // templates, so we disable the warning.
  75. #pragma warning( disable: 4514 )
  76. #endif
  77. #define NSCAP_FEATURE_USE_BASE
  78. #ifdef NS_DEBUG
  79. #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
  80. #undef NSCAP_FEATURE_USE_BASE
  81. //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
  82. #endif
  83. /*
  84. |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
  85. problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing
  86. a mechanism by which these features can be explicitly disabled from the command-line.
  87. */
  88. #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
  89. #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  90. #endif
  91. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
  92. // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
  93. // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
  94. // don't reorder instructions based on aliasing assumptions for
  95. // this variable. Fortunately, gcc versions < 3.3 do not do any
  96. // optimizations that break nsCOMPtr.
  97. #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
  98. #else
  99. #define NS_MAY_ALIAS_PTR(t) t*
  100. #endif
  101. #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
  102. #define NSCAP_FEATURE_USE_BASE
  103. #endif
  104. #ifdef HAVE_CPP_BOOL
  105. typedef bool NSCAP_BOOL;
  106. #else
  107. typedef PRBool NSCAP_BOOL;
  108. #endif
  109. /*
  110. The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
  111. allow external clients the ability to add logging or other interesting debug facilities.
  112. In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
  113. provide (e.g., in "nsTraceRefcnt.h") suitable definitions
  114. #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
  115. #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
  116. */
  117. #ifndef NSCAP_ADDREF
  118. #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
  119. #endif
  120. #ifndef NSCAP_RELEASE
  121. #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
  122. #endif
  123. // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
  124. #ifdef NSCAP_LOG_ASSIGNMENT
  125. // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
  126. // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
  127. // the |nsCOMPtr|.
  128. #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
  129. #else
  130. // ...otherwise, just strip it out of the code
  131. #define NSCAP_LOG_ASSIGNMENT(this, ptr)
  132. #endif
  133. #ifndef NSCAP_LOG_RELEASE
  134. #define NSCAP_LOG_RELEASE(this, ptr)
  135. #endif
  136. /*
  137. WARNING:
  138. VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
  139. in an order that satisfies:
  140. nsDerivedSafe < nsCOMPtr
  141. already_AddRefed < nsCOMPtr
  142. nsCOMPtr < nsGetterAddRefs
  143. The other compilers probably won't complain, so please don't reorder these
  144. classes, on pain of breaking 4.2 compatibility.
  145. */
  146. template <class T>
  147. class nsDerivedSafe : public T
  148. /*
  149. No client should ever see or have to type the name of this class. It is the
  150. artifact that makes it a compile-time error to call |AddRef| and |Release|
  151. on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
  152. See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
  153. This type should be a nested class inside |nsCOMPtr<T>|.
  154. */
  155. {
  156. private:
  157. #ifdef HAVE_CPP_ACCESS_CHANGING_USING
  158. using T::AddRef;
  159. using T::Release;
  160. #else
  161. nsrefcnt AddRef(void);
  162. nsrefcnt Release(void);
  163. #endif
  164. #if !defined(AIX) && !defined(IRIX)
  165. void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED
  166. // declaring |operator delete| private makes calling delete on an interface pointer a compile error
  167. #endif
  168. nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED
  169. // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
  170. /*
  171. Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
  172. If you see that, that means somebody checked in a [XP]COM interface class that declares an
  173. |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly
  174. to stop people from doing it.
  175. */
  176. protected:
  177. nsDerivedSafe(); // NOT TO BE IMPLEMENTED
  178. /*
  179. This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
  180. default ctor but inheriting classes without an empty ctor. See bug 209667.
  181. */
  182. };
  183. #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
  184. template <class T>
  185. nsrefcnt
  186. nsDerivedSafe<T>::AddRef()
  187. {
  188. return 0;
  189. }
  190. template <class T>
  191. nsrefcnt
  192. nsDerivedSafe<T>::Release()
  193. {
  194. return 0;
  195. }
  196. #endif
  197. template <class T>
  198. struct already_AddRefed
  199. /*
  200. ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
  201. |AddRef|ing it. You might want to use this as a return type from a function
  202. that produces an already |AddRef|ed pointer as a result.
  203. See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
  204. This type should be a nested class inside |nsCOMPtr<T>|.
  205. Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
  206. avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
  207. case, and perhaps worth the savings in time and space that its specific
  208. implementation affords over the more general solution offered by
  209. |nsCOMPtr_helper|.
  210. */
  211. {
  212. already_AddRefed( T* aRawPtr )
  213. : mRawPtr(aRawPtr)
  214. {
  215. // nothing else to do here
  216. }
  217. T* get() const { return mRawPtr; }
  218. T* mRawPtr;
  219. };
  220. template <class T>
  221. inline
  222. const already_AddRefed<T>
  223. getter_AddRefs( T* aRawPtr )
  224. /*
  225. ...makes typing easier, because it deduces the template type, e.g.,
  226. you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
  227. */
  228. {
  229. return already_AddRefed<T>(aRawPtr);
  230. }
  231. template <class T>
  232. inline
  233. const already_AddRefed<T>
  234. getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
  235. {
  236. return aAlreadyAddRefedPtr;
  237. }
  238. template <class T>
  239. inline
  240. const already_AddRefed<T>
  241. dont_AddRef( T* aRawPtr )
  242. {
  243. return already_AddRefed<T>(aRawPtr);
  244. }
  245. template <class T>
  246. inline
  247. const already_AddRefed<T>
  248. dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
  249. {
  250. return aAlreadyAddRefedPtr;
  251. }
  252. class nsCOMPtr_helper
  253. /*
  254. An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
  255. that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
  256. Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
  257. Here are the rules for a helper:
  258. - it implements |operator()| to produce an interface pointer
  259. - (except for its name) |operator()| is a valid [XP]COM `getter'
  260. - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
  261. - it matches the type requested with the supplied |nsIID| argument
  262. - its constructor provides an optional |nsresult*| that |operator()| can fill
  263. in with an error when it is executed
  264. See |class nsGetInterface| for an example.
  265. */
  266. {
  267. public:
  268. virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
  269. };
  270. /*
  271. |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
  272. avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
  273. is called often enough that the codesize savings are big enough to
  274. warrant the specialcasing.
  275. */
  276. class NS_COM_GLUE nsQueryInterface
  277. {
  278. public:
  279. explicit
  280. nsQueryInterface( nsISupports* aRawPtr )
  281. : mRawPtr(aRawPtr)
  282. {
  283. // nothing else to do here
  284. }
  285. nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  286. private:
  287. nsISupports* mRawPtr;
  288. };
  289. class NS_COM_GLUE nsQueryInterfaceWithError
  290. {
  291. public:
  292. nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
  293. : mRawPtr(aRawPtr),
  294. mErrorPtr(error)
  295. {
  296. // nothing else to do here
  297. }
  298. nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  299. private:
  300. nsISupports* mRawPtr;
  301. nsresult* mErrorPtr;
  302. };
  303. inline
  304. nsQueryInterface
  305. do_QueryInterface( nsISupports* aRawPtr )
  306. {
  307. return nsQueryInterface(aRawPtr);
  308. }
  309. inline
  310. nsQueryInterfaceWithError
  311. do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
  312. {
  313. return nsQueryInterfaceWithError(aRawPtr, error);
  314. }
  315. template <class T>
  316. inline
  317. void
  318. do_QueryInterface( already_AddRefed<T>& )
  319. {
  320. // This signature exists solely to _stop_ you from doing the bad thing.
  321. // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  322. // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  323. }
  324. template <class T>
  325. inline
  326. void
  327. do_QueryInterface( already_AddRefed<T>&, nsresult* )
  328. {
  329. // This signature exists solely to _stop_ you from doing the bad thing.
  330. // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  331. // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  332. }
  333. ////////////////////////////////////////////////////////////////////////////
  334. // Using servicemanager with COMPtrs
  335. class NS_COM_GLUE nsGetServiceByCID
  336. {
  337. public:
  338. explicit nsGetServiceByCID(const nsCID& aCID)
  339. : mCID(aCID)
  340. {
  341. // nothing else to do
  342. }
  343. nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  344. private:
  345. const nsCID& mCID;
  346. };
  347. class NS_COM_GLUE nsGetServiceByCIDWithError
  348. {
  349. public:
  350. nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
  351. : mCID(aCID),
  352. mErrorPtr(aErrorPtr)
  353. {
  354. // nothing else to do
  355. }
  356. nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  357. private:
  358. const nsCID& mCID;
  359. nsresult* mErrorPtr;
  360. };
  361. class NS_COM_GLUE nsGetServiceByContractID
  362. {
  363. public:
  364. explicit nsGetServiceByContractID(const char* aContractID)
  365. : mContractID(aContractID)
  366. {
  367. // nothing else to do
  368. }
  369. nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  370. private:
  371. const char* mContractID;
  372. };
  373. class NS_COM_GLUE nsGetServiceByContractIDWithError
  374. {
  375. public:
  376. nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
  377. : mContractID(aContractID),
  378. mErrorPtr(aErrorPtr)
  379. {
  380. // nothing else to do
  381. }
  382. nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  383. private:
  384. const char* mContractID;
  385. nsresult* mErrorPtr;
  386. };
  387. class nsCOMPtr_base
  388. /*
  389. ...factors implementation for all template versions of |nsCOMPtr|.
  390. This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
  391. because unlike the
  392. Here's the way people normally do things like this
  393. template <class T> class Foo { ... };
  394. template <> class Foo<void*> { ... };
  395. template <class T> class Foo<T*> : private Foo<void*> { ... };
  396. */
  397. {
  398. public:
  399. nsCOMPtr_base( nsISupports* rawPtr = 0 )
  400. : mRawPtr(rawPtr)
  401. {
  402. // nothing else to do here
  403. }
  404. NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base();
  405. NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* );
  406. NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
  407. NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  408. NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  409. NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  410. NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  411. NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  412. NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  413. NS_COM_GLUE void** NS_FASTCALL begin_assignment();
  414. protected:
  415. NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
  416. void
  417. assign_assuming_AddRef( nsISupports* newPtr )
  418. {
  419. /*
  420. |AddRef()|ing the new value (before entering this function) before
  421. |Release()|ing the old lets us safely ignore the self-assignment case.
  422. We must, however, be careful only to |Release()| _after_ doing the
  423. assignment, in case the |Release()| leads to our _own_ destruction,
  424. which would, in turn, cause an incorrect second |Release()| of our old
  425. pointer. Thank <waterson@netscape.com> for discovering this.
  426. */
  427. nsISupports* oldPtr = mRawPtr;
  428. mRawPtr = newPtr;
  429. NSCAP_LOG_ASSIGNMENT(this, newPtr);
  430. NSCAP_LOG_RELEASE(this, oldPtr);
  431. if ( oldPtr )
  432. NSCAP_RELEASE(this, oldPtr);
  433. }
  434. };
  435. // template <class T> class nsGetterAddRefs;
  436. template <class T>
  437. class nsCOMPtr
  438. #ifdef NSCAP_FEATURE_USE_BASE
  439. : private nsCOMPtr_base
  440. #endif
  441. {
  442. #ifdef NSCAP_FEATURE_USE_BASE
  443. #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
  444. #else
  445. #define NSCAP_CTOR_BASE(x) mRawPtr(x)
  446. private:
  447. void assign_with_AddRef( nsISupports* );
  448. void assign_from_qi( const nsQueryInterface, const nsIID& );
  449. void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  450. void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  451. void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  452. void assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  453. void assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  454. void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  455. void** begin_assignment();
  456. void
  457. assign_assuming_AddRef( T* newPtr )
  458. {
  459. T* oldPtr = mRawPtr;
  460. mRawPtr = newPtr;
  461. NSCAP_LOG_ASSIGNMENT(this, newPtr);
  462. NSCAP_LOG_RELEASE(this, oldPtr);
  463. if ( oldPtr )
  464. NSCAP_RELEASE(this, oldPtr);
  465. }
  466. private:
  467. T* mRawPtr;
  468. #endif
  469. public:
  470. typedef T element_type;
  471. #ifndef NSCAP_FEATURE_USE_BASE
  472. ~nsCOMPtr()
  473. {
  474. NSCAP_LOG_RELEASE(this, mRawPtr);
  475. if ( mRawPtr )
  476. NSCAP_RELEASE(this, mRawPtr);
  477. }
  478. #endif
  479. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  480. void
  481. Assert_NoQueryNeeded()
  482. {
  483. if ( mRawPtr )
  484. {
  485. nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
  486. NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
  487. }
  488. }
  489. #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
  490. #else
  491. #define NSCAP_ASSERT_NO_QUERY_NEEDED()
  492. #endif
  493. // Constructors
  494. nsCOMPtr()
  495. : NSCAP_CTOR_BASE(0)
  496. // default constructor
  497. {
  498. NSCAP_LOG_ASSIGNMENT(this, 0);
  499. }
  500. nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
  501. : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  502. // copy-constructor
  503. {
  504. if ( mRawPtr )
  505. NSCAP_ADDREF(this, mRawPtr);
  506. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  507. }
  508. nsCOMPtr( T* aRawPtr )
  509. : NSCAP_CTOR_BASE(aRawPtr)
  510. // construct from a raw pointer (of the right type)
  511. {
  512. if ( mRawPtr )
  513. NSCAP_ADDREF(this, mRawPtr);
  514. NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  515. NSCAP_ASSERT_NO_QUERY_NEEDED();
  516. }
  517. nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
  518. : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  519. // construct from |dont_AddRef(expr)|
  520. {
  521. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  522. NSCAP_ASSERT_NO_QUERY_NEEDED();
  523. }
  524. nsCOMPtr( const nsQueryInterface qi )
  525. : NSCAP_CTOR_BASE(0)
  526. // construct from |do_QueryInterface(expr)|
  527. {
  528. NSCAP_LOG_ASSIGNMENT(this, 0);
  529. assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
  530. }
  531. nsCOMPtr( const nsQueryInterfaceWithError& qi )
  532. : NSCAP_CTOR_BASE(0)
  533. // construct from |do_QueryInterface(expr, &rv)|
  534. {
  535. NSCAP_LOG_ASSIGNMENT(this, 0);
  536. assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
  537. }
  538. nsCOMPtr( const nsGetServiceByCID gs )
  539. : NSCAP_CTOR_BASE(0)
  540. // construct from |do_GetService(cid_expr)|
  541. {
  542. NSCAP_LOG_ASSIGNMENT(this, 0);
  543. assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
  544. }
  545. nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  546. : NSCAP_CTOR_BASE(0)
  547. // construct from |do_GetService(cid_expr, &rv)|
  548. {
  549. NSCAP_LOG_ASSIGNMENT(this, 0);
  550. assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
  551. }
  552. nsCOMPtr( const nsGetServiceByContractID gs )
  553. : NSCAP_CTOR_BASE(0)
  554. // construct from |do_GetService(contractid_expr)|
  555. {
  556. NSCAP_LOG_ASSIGNMENT(this, 0);
  557. assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
  558. }
  559. nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  560. : NSCAP_CTOR_BASE(0)
  561. // construct from |do_GetService(contractid_expr, &rv)|
  562. {
  563. NSCAP_LOG_ASSIGNMENT(this, 0);
  564. assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
  565. }
  566. nsCOMPtr( const nsCOMPtr_helper& helper )
  567. : NSCAP_CTOR_BASE(0)
  568. // ...and finally, anything else we might need to construct from
  569. // can exploit the |nsCOMPtr_helper| facility
  570. {
  571. NSCAP_LOG_ASSIGNMENT(this, 0);
  572. assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
  573. NSCAP_ASSERT_NO_QUERY_NEEDED();
  574. }
  575. // Assignment operators
  576. nsCOMPtr<T>&
  577. operator=( const nsCOMPtr<T>& rhs )
  578. // copy assignment operator
  579. {
  580. assign_with_AddRef(rhs.mRawPtr);
  581. return *this;
  582. }
  583. nsCOMPtr<T>&
  584. operator=( T* rhs )
  585. // assign from a raw pointer (of the right type)
  586. {
  587. assign_with_AddRef(rhs);
  588. NSCAP_ASSERT_NO_QUERY_NEEDED();
  589. return *this;
  590. }
  591. nsCOMPtr<T>&
  592. operator=( const already_AddRefed<T>& rhs )
  593. // assign from |dont_AddRef(expr)|
  594. {
  595. assign_assuming_AddRef(rhs.mRawPtr);
  596. NSCAP_ASSERT_NO_QUERY_NEEDED();
  597. return *this;
  598. }
  599. nsCOMPtr<T>&
  600. operator=( const nsQueryInterface rhs )
  601. // assign from |do_QueryInterface(expr)|
  602. {
  603. assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
  604. return *this;
  605. }
  606. nsCOMPtr<T>&
  607. operator=( const nsQueryInterfaceWithError& rhs )
  608. // assign from |do_QueryInterface(expr, &rv)|
  609. {
  610. assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
  611. return *this;
  612. }
  613. nsCOMPtr<T>&
  614. operator=( const nsGetServiceByCID rhs )
  615. // assign from |do_GetService(cid_expr)|
  616. {
  617. assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
  618. return *this;
  619. }
  620. nsCOMPtr<T>&
  621. operator=( const nsGetServiceByCIDWithError& rhs )
  622. // assign from |do_GetService(cid_expr, &rv)|
  623. {
  624. assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
  625. return *this;
  626. }
  627. nsCOMPtr<T>&
  628. operator=( const nsGetServiceByContractID rhs )
  629. // assign from |do_GetService(contractid_expr)|
  630. {
  631. assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
  632. return *this;
  633. }
  634. nsCOMPtr<T>&
  635. operator=( const nsGetServiceByContractIDWithError& rhs )
  636. // assign from |do_GetService(contractid_expr, &rv)|
  637. {
  638. assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
  639. return *this;
  640. }
  641. nsCOMPtr<T>&
  642. operator=( const nsCOMPtr_helper& rhs )
  643. // ...and finally, anything else we might need to assign from
  644. // can exploit the |nsCOMPtr_helper| facility.
  645. {
  646. assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
  647. NSCAP_ASSERT_NO_QUERY_NEEDED();
  648. return *this;
  649. }
  650. void
  651. swap( nsCOMPtr<T>& rhs )
  652. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  653. {
  654. #ifdef NSCAP_FEATURE_USE_BASE
  655. nsISupports* temp = rhs.mRawPtr;
  656. #else
  657. T* temp = rhs.mRawPtr;
  658. #endif
  659. NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  660. NSCAP_LOG_ASSIGNMENT(this, temp);
  661. NSCAP_LOG_RELEASE(this, mRawPtr);
  662. NSCAP_LOG_RELEASE(&rhs, temp);
  663. rhs.mRawPtr = mRawPtr;
  664. mRawPtr = temp;
  665. // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
  666. }
  667. void
  668. swap( T*& rhs )
  669. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  670. {
  671. #ifdef NSCAP_FEATURE_USE_BASE
  672. nsISupports* temp = rhs;
  673. #else
  674. T* temp = rhs;
  675. #endif
  676. NSCAP_LOG_ASSIGNMENT(this, temp);
  677. NSCAP_LOG_RELEASE(this, mRawPtr);
  678. rhs = reinterpret_cast<T*>(mRawPtr);
  679. mRawPtr = temp;
  680. NSCAP_ASSERT_NO_QUERY_NEEDED();
  681. }
  682. // Other pointer operators
  683. already_AddRefed<T>
  684. forget()
  685. // return the value of mRawPtr and null out mRawPtr. Useful for
  686. // already_AddRefed return values.
  687. {
  688. T* temp = 0;
  689. swap(temp);
  690. return temp;
  691. }
  692. void
  693. forget( T** rhs )
  694. // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
  695. // Useful to avoid unnecessary AddRef/Release pairs with "out"
  696. // parameters.
  697. {
  698. NS_ASSERTION(rhs, "Null pointer passed to forget!");
  699. *rhs = 0;
  700. swap(*rhs);
  701. }
  702. T*
  703. get() const
  704. /*
  705. Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
  706. Use |get()| to resolve ambiguity or to get a castable pointer.
  707. */
  708. {
  709. return reinterpret_cast<T*>(mRawPtr);
  710. }
  711. operator nsDerivedSafe<T>*() const
  712. /*
  713. ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  714. and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
  715. that makes an |nsCOMPtr| substitutable for a raw pointer.
  716. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  717. */
  718. {
  719. return get_DerivedSafe();
  720. }
  721. nsDerivedSafe<T>*
  722. operator->() const
  723. {
  724. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  725. return get_DerivedSafe();
  726. }
  727. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  728. // broken version for IRIX
  729. nsCOMPtr<T>*
  730. get_address() const
  731. // This is not intended to be used by clients. See |address_of|
  732. // below.
  733. {
  734. return const_cast<nsCOMPtr<T>*>(this);
  735. }
  736. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  737. nsCOMPtr<T>*
  738. get_address()
  739. // This is not intended to be used by clients. See |address_of|
  740. // below.
  741. {
  742. return this;
  743. }
  744. const nsCOMPtr<T>*
  745. get_address() const
  746. // This is not intended to be used by clients. See |address_of|
  747. // below.
  748. {
  749. return this;
  750. }
  751. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  752. public:
  753. nsDerivedSafe<T>&
  754. operator*() const
  755. {
  756. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  757. return *get_DerivedSafe();
  758. }
  759. #if 0
  760. private:
  761. friend class nsGetterAddRefs<T>;
  762. #endif
  763. T**
  764. StartAssignment()
  765. {
  766. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  767. return reinterpret_cast<T**>(begin_assignment());
  768. #else
  769. assign_assuming_AddRef(0);
  770. return reinterpret_cast<T**>(&mRawPtr);
  771. #endif
  772. }
  773. private:
  774. nsDerivedSafe<T>*
  775. get_DerivedSafe() const
  776. {
  777. return reinterpret_cast<nsDerivedSafe<T>*>(mRawPtr);
  778. }
  779. };
  780. /*
  781. Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
  782. same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
  783. to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
  784. to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
  785. querying ensues. Clients need to be able to pass around arbitrary interface pointers,
  786. without hassles, through intermediary code that doesn't know the exact type.
  787. */
  788. NS_SPECIALIZE_TEMPLATE
  789. class nsCOMPtr<nsISupports>
  790. : private nsCOMPtr_base
  791. {
  792. public:
  793. typedef nsISupports element_type;
  794. // Constructors
  795. nsCOMPtr()
  796. : nsCOMPtr_base(0)
  797. // default constructor
  798. {
  799. NSCAP_LOG_ASSIGNMENT(this, 0);
  800. }
  801. nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
  802. : nsCOMPtr_base(aSmartPtr.mRawPtr)
  803. // copy constructor
  804. {
  805. if ( mRawPtr )
  806. NSCAP_ADDREF(this, mRawPtr);
  807. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  808. }
  809. nsCOMPtr( nsISupports* aRawPtr )
  810. : nsCOMPtr_base(aRawPtr)
  811. // construct from a raw pointer (of the right type)
  812. {
  813. if ( mRawPtr )
  814. NSCAP_ADDREF(this, mRawPtr);
  815. NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  816. }
  817. nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
  818. : nsCOMPtr_base(aSmartPtr.mRawPtr)
  819. // construct from |dont_AddRef(expr)|
  820. {
  821. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  822. }
  823. nsCOMPtr( const nsQueryInterface qi )
  824. : nsCOMPtr_base(0)
  825. // assign from |do_QueryInterface(expr)|
  826. {
  827. NSCAP_LOG_ASSIGNMENT(this, 0);
  828. assign_from_qi(qi, NS_GET_IID(nsISupports));
  829. }
  830. nsCOMPtr( const nsQueryInterfaceWithError& qi )
  831. : nsCOMPtr_base(0)
  832. // assign from |do_QueryInterface(expr, &rv)|
  833. {
  834. NSCAP_LOG_ASSIGNMENT(this, 0);
  835. assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
  836. }
  837. nsCOMPtr( const nsGetServiceByCID gs )
  838. : nsCOMPtr_base(0)
  839. // assign from |do_GetService(cid_expr)|
  840. {
  841. NSCAP_LOG_ASSIGNMENT(this, 0);
  842. assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
  843. }
  844. nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  845. : nsCOMPtr_base(0)
  846. // assign from |do_GetService(cid_expr, &rv)|
  847. {
  848. NSCAP_LOG_ASSIGNMENT(this, 0);
  849. assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
  850. }
  851. nsCOMPtr( const nsGetServiceByContractID gs )
  852. : nsCOMPtr_base(0)
  853. // assign from |do_GetService(contractid_expr)|
  854. {
  855. NSCAP_LOG_ASSIGNMENT(this, 0);
  856. assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
  857. }
  858. nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  859. : nsCOMPtr_base(0)
  860. // assign from |do_GetService(contractid_expr, &rv)|
  861. {
  862. NSCAP_LOG_ASSIGNMENT(this, 0);
  863. assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
  864. }
  865. nsCOMPtr( const nsCOMPtr_helper& helper )
  866. : nsCOMPtr_base(0)
  867. // ...and finally, anything else we might need to construct from
  868. // can exploit the |nsCOMPtr_helper| facility
  869. {
  870. NSCAP_LOG_ASSIGNMENT(this, 0);
  871. assign_from_helper(helper, NS_GET_IID(nsISupports));
  872. }
  873. // Assignment operators
  874. nsCOMPtr<nsISupports>&
  875. operator=( const nsCOMPtr<nsISupports>& rhs )
  876. // copy assignment operator
  877. {
  878. assign_with_AddRef(rhs.mRawPtr);
  879. return *this;
  880. }
  881. nsCOMPtr<nsISupports>&
  882. operator=( nsISupports* rhs )
  883. // assign from a raw pointer (of the right type)
  884. {
  885. assign_with_AddRef(rhs);
  886. return *this;
  887. }
  888. nsCOMPtr<nsISupports>&
  889. operator=( const already_AddRefed<nsISupports>& rhs )
  890. // assign from |dont_AddRef(expr)|
  891. {
  892. assign_assuming_AddRef(rhs.mRawPtr);
  893. return *this;
  894. }
  895. nsCOMPtr<nsISupports>&
  896. operator=( const nsQueryInterface rhs )
  897. // assign from |do_QueryInterface(expr)|
  898. {
  899. assign_from_qi(rhs, NS_GET_IID(nsISupports));
  900. return *this;
  901. }
  902. nsCOMPtr<nsISupports>&
  903. operator=( const nsQueryInterfaceWithError& rhs )
  904. // assign from |do_QueryInterface(expr, &rv)|
  905. {
  906. assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
  907. return *this;
  908. }
  909. nsCOMPtr<nsISupports>&
  910. operator=( const nsGetServiceByCID rhs )
  911. // assign from |do_GetService(cid_expr)|
  912. {
  913. assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
  914. return *this;
  915. }
  916. nsCOMPtr<nsISupports>&
  917. operator=( const nsGetServiceByCIDWithError& rhs )
  918. // assign from |do_GetService(cid_expr, &rv)|
  919. {
  920. assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
  921. return *this;
  922. }
  923. nsCOMPtr<nsISupports>&
  924. operator=( const nsGetServiceByContractID rhs )
  925. // assign from |do_GetService(contractid_expr)|
  926. {
  927. assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
  928. return *this;
  929. }
  930. nsCOMPtr<nsISupports>&
  931. operator=( const nsGetServiceByContractIDWithError& rhs )
  932. // assign from |do_GetService(contractid_expr, &rv)|
  933. {
  934. assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
  935. return *this;
  936. }
  937. nsCOMPtr<nsISupports>&
  938. operator=( const nsCOMPtr_helper& rhs )
  939. // ...and finally, anything else we might need to assign from
  940. // can exploit the |nsCOMPtr_helper| facility.
  941. {
  942. assign_from_helper(rhs, NS_GET_IID(nsISupports));
  943. return *this;
  944. }
  945. void
  946. swap( nsCOMPtr<nsISupports>& rhs )
  947. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  948. {
  949. nsISupports* temp = rhs.mRawPtr;
  950. NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  951. NSCAP_LOG_ASSIGNMENT(this, temp);
  952. NSCAP_LOG_RELEASE(this, mRawPtr);
  953. NSCAP_LOG_RELEASE(&rhs, temp);
  954. rhs.mRawPtr = mRawPtr;
  955. mRawPtr = temp;
  956. }
  957. void
  958. swap( nsISupports*& rhs )
  959. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  960. {
  961. nsISupports* temp = rhs;
  962. NSCAP_LOG_ASSIGNMENT(this, temp);
  963. NSCAP_LOG_RELEASE(this, mRawPtr);
  964. rhs = mRawPtr;
  965. mRawPtr = temp;
  966. }
  967. void
  968. forget( nsISupports** rhs )
  969. // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
  970. // Useful to avoid unnecessary AddRef/Release pairs with "out"
  971. // parameters.
  972. {
  973. NS_ASSERTION(rhs, "Null pointer passed to forget!");
  974. *rhs = 0;
  975. swap(*rhs);
  976. }
  977. // Other pointer operators
  978. nsISupports*
  979. get() const
  980. /*
  981. Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
  982. Use |get()| to resolve ambiguity or to get a castable pointer.
  983. */
  984. {
  985. return reinterpret_cast<nsISupports*>(mRawPtr);
  986. }
  987. operator nsDerivedSafe<nsISupports>*() const
  988. /*
  989. ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  990. and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
  991. that makes an |nsCOMPtr| substitutable for a raw pointer.
  992. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  993. */
  994. {
  995. return get_DerivedSafe();
  996. }
  997. nsDerivedSafe<nsISupports>*
  998. operator->() const
  999. {
  1000. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  1001. return get_DerivedSafe();
  1002. }
  1003. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1004. // broken version for IRIX
  1005. nsCOMPtr<nsISupports>*
  1006. get_address() const
  1007. // This is not intended to be used by clients. See |address_of|
  1008. // below.
  1009. {
  1010. return const_cast<nsCOMPtr<nsISupports>*>(this);
  1011. }
  1012. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1013. nsCOMPtr<nsISupports>*
  1014. get_address()
  1015. // This is not intended to be used by clients. See |address_of|
  1016. // below.
  1017. {
  1018. return this;
  1019. }
  1020. const nsCOMPtr<nsISupports>*
  1021. get_address() const
  1022. // This is not intended to be used by clients. See |address_of|
  1023. // below.
  1024. {
  1025. return this;
  1026. }
  1027. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1028. public:
  1029. nsDerivedSafe<nsISupports>&
  1030. operator*() const
  1031. {
  1032. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  1033. return *get_DerivedSafe();
  1034. }
  1035. #if 0
  1036. private:
  1037. friend class nsGetterAddRefs<nsISupports>;
  1038. #endif
  1039. nsISupports**
  1040. StartAssignment()
  1041. {
  1042. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  1043. return reinterpret_cast<nsISupports**>(begin_assignment());
  1044. #else
  1045. assign_assuming_AddRef(0);
  1046. return reinterpret_cast<nsISupports**>(&mRawPtr);
  1047. #endif
  1048. }
  1049. private:
  1050. nsDerivedSafe<nsISupports>*
  1051. get_DerivedSafe() const
  1052. {
  1053. return reinterpret_cast<nsDerivedSafe<nsISupports>*>(mRawPtr);
  1054. }
  1055. };
  1056. #ifndef NSCAP_FEATURE_USE_BASE
  1057. template <class T>
  1058. void
  1059. nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
  1060. {
  1061. if ( rawPtr )
  1062. NSCAP_ADDREF(this, rawPtr);
  1063. assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
  1064. }
  1065. template <class T>
  1066. void
  1067. nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
  1068. {
  1069. void* newRawPtr;
  1070. if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
  1071. newRawPtr = 0;
  1072. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1073. }
  1074. template <class T>
  1075. void
  1076. nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
  1077. {
  1078. void* newRawPtr;
  1079. if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
  1080. newRawPtr = 0;
  1081. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1082. }
  1083. template <class T>
  1084. void
  1085. nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
  1086. {
  1087. void* newRawPtr;
  1088. if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1089. newRawPtr = 0;
  1090. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1091. }
  1092. template <class T>
  1093. void
  1094. nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
  1095. {
  1096. void* newRawPtr;
  1097. if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1098. newRawPtr = 0;
  1099. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1100. }
  1101. template <class T>
  1102. void
  1103. nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
  1104. {
  1105. void* newRawPtr;
  1106. if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1107. newRawPtr = 0;
  1108. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1109. }
  1110. template <class T>
  1111. void
  1112. nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
  1113. {
  1114. void* newRawPtr;
  1115. if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
  1116. newRawPtr = 0;
  1117. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1118. }
  1119. template <class T>
  1120. void
  1121. nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
  1122. {
  1123. void* newRawPtr;
  1124. if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
  1125. newRawPtr = 0;
  1126. assign_assuming_AddRef(static_cast<T*>(newRawPtr));
  1127. }
  1128. template <class T>
  1129. void**
  1130. nsCOMPtr<T>::begin_assignment()
  1131. {
  1132. assign_assuming_AddRef(0);
  1133. union { T** mT; void** mVoid; } result;
  1134. result.mT = &mRawPtr;
  1135. return result.mVoid;
  1136. }
  1137. #endif
  1138. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1139. // This is the broken version for IRIX, which can't handle the version below.
  1140. template <class T>
  1141. inline
  1142. nsCOMPtr<T>*
  1143. address_of( const nsCOMPtr<T>& aPtr )
  1144. {
  1145. return aPtr.get_address();
  1146. }
  1147. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1148. template <class T>
  1149. inline
  1150. nsCOMPtr<T>*
  1151. address_of( nsCOMPtr<T>& aPtr )
  1152. {
  1153. return aPtr.get_address();
  1154. }
  1155. template <class T>
  1156. inline
  1157. const nsCOMPtr<T>*
  1158. address_of( const nsCOMPtr<T>& aPtr )
  1159. {
  1160. return aPtr.get_address();
  1161. }
  1162. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1163. template <class T>
  1164. class nsGetterAddRefs
  1165. /*
  1166. ...
  1167. This class is designed to be used for anonymous temporary objects in the
  1168. argument list of calls that return COM interface pointers, e.g.,
  1169. nsCOMPtr<IFoo> fooP;
  1170. ...->QueryInterface(iid, getter_AddRefs(fooP))
  1171. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
  1172. When initialized with a |nsCOMPtr|, as in the example above, it returns
  1173. a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
  1174. case) can fill in.
  1175. This type should be a nested class inside |nsCOMPtr<T>|.
  1176. */
  1177. {
  1178. public:
  1179. explicit
  1180. nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
  1181. : mTargetSmartPtr(aSmartPtr)
  1182. {
  1183. // nothing else to do
  1184. }
  1185. #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
  1186. ~nsGetterAddRefs()
  1187. {
  1188. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1189. NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1190. #endif
  1191. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  1192. mTargetSmartPtr.Assert_NoQueryNeeded();
  1193. #endif
  1194. }
  1195. #endif
  1196. operator void**()
  1197. {
  1198. return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  1199. }
  1200. operator nsISupports**()
  1201. {
  1202. return reinterpret_cast<nsISupports**>(mTargetSmartPtr.StartAssignment());
  1203. }
  1204. operator T**()
  1205. {
  1206. return mTargetSmartPtr.StartAssignment();
  1207. }
  1208. T*&
  1209. operator*()
  1210. {
  1211. return *(mTargetSmartPtr.StartAssignment());
  1212. }
  1213. private:
  1214. nsCOMPtr<T>& mTargetSmartPtr;
  1215. };
  1216. NS_SPECIALIZE_TEMPLATE
  1217. class nsGetterAddRefs<nsISupports>
  1218. {
  1219. public:
  1220. explicit
  1221. nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
  1222. : mTargetSmartPtr(aSmartPtr)
  1223. {
  1224. // nothing else to do
  1225. }
  1226. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1227. ~nsGetterAddRefs()
  1228. {
  1229. NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1230. }
  1231. #endif
  1232. operator void**()
  1233. {
  1234. return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  1235. }
  1236. operator nsISupports**()
  1237. {
  1238. return mTargetSmartPtr.StartAssignment();
  1239. }
  1240. nsISupports*&
  1241. operator*()
  1242. {
  1243. return *(mTargetSmartPtr.StartAssignment());
  1244. }
  1245. private:
  1246. nsCOMPtr<nsISupports>& mTargetSmartPtr;
  1247. };
  1248. template <class T>
  1249. inline
  1250. nsGetterAddRefs<T>
  1251. getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
  1252. /*
  1253. Used around a |nsCOMPtr| when
  1254. ...makes the class |nsGetterAddRefs<T>| invisible.
  1255. */
  1256. {
  1257. return nsGetterAddRefs<T>(aSmartPtr);
  1258. }
  1259. // Comparing two |nsCOMPtr|s
  1260. template <class T, class U>
  1261. inline
  1262. NSCAP_BOOL
  1263. operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1264. {
  1265. return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
  1266. }
  1267. template <class T, class U>
  1268. inline
  1269. NSCAP_BOOL
  1270. operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1271. {
  1272. return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
  1273. }
  1274. // Comparing an |nsCOMPtr| to a raw pointer
  1275. template <class T, class U>
  1276. inline
  1277. NSCAP_BOOL
  1278. operator==( const nsCOMPtr<T>& lhs, const U* rhs )
  1279. {
  1280. return static_cast<const T*>(lhs.get()) == rhs;
  1281. }
  1282. template <class T, class U>
  1283. inline
  1284. NSCAP_BOOL
  1285. operator==( const U* lhs, const nsCOMPtr<T>& rhs )
  1286. {
  1287. return lhs == static_cast<const T*>(rhs.get());
  1288. }
  1289. template <class T, class U>
  1290. inline
  1291. NSCAP_BOOL
  1292. operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
  1293. {
  1294. return static_cast<const T*>(lhs.get()) != rhs;
  1295. }
  1296. template <class T, class U>
  1297. inline
  1298. NSCAP_BOOL
  1299. operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
  1300. {
  1301. return lhs != static_cast<const T*>(rhs.get());
  1302. }
  1303. // To avoid ambiguities caused by the presence of builtin |operator==|s
  1304. // creating a situation where one of the |operator==| defined above
  1305. // has a better conversion for one argument and the builtin has a
  1306. // better conversion for the other argument, define additional
  1307. // |operator==| without the |const| on the raw pointer.
  1308. // See bug 65664 for details.
  1309. // This is defined by an autoconf test, but VC++ also has a bug that
  1310. // prevents us from using these. (It also, fortunately, has the bug
  1311. // that we don't need them either.)
  1312. #if defined(_MSC_VER) && (_MSC_VER < 1310)
  1313. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1314. #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1315. #endif
  1316. #endif
  1317. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1318. template <class T, class U>
  1319. inline
  1320. NSCAP_BOOL
  1321. operator==( const nsCOMPtr<T>& lhs, U* rhs )
  1322. {
  1323. return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
  1324. }
  1325. template <class T, class U>
  1326. inline
  1327. NSCAP_BOOL
  1328. operator==( U* lhs, const nsCOMPtr<T>& rhs )
  1329. {
  1330. return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
  1331. }
  1332. template <class T, class U>
  1333. inline
  1334. NSCAP_BOOL
  1335. operator!=( const nsCOMPtr<T>& lhs, U* rhs )
  1336. {
  1337. return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
  1338. }
  1339. template <class T, class U>
  1340. inline
  1341. NSCAP_BOOL
  1342. operator!=( U* lhs, const nsCOMPtr<T>& rhs )
  1343. {
  1344. return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
  1345. }
  1346. #endif
  1347. // Comparing an |nsCOMPtr| to |0|
  1348. class NSCAP_Zero;
  1349. template <class T>
  1350. inline
  1351. NSCAP_BOOL
  1352. operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1353. // specifically to allow |smartPtr == 0|
  1354. {
  1355. return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
  1356. }
  1357. template <class T>
  1358. inline
  1359. NSCAP_BOOL
  1360. operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1361. // specifically to allow |0 == smartPtr|
  1362. {
  1363. return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
  1364. }
  1365. template <class T>
  1366. inline
  1367. NSCAP_BOOL
  1368. operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1369. // specifically to allow |smartPtr != 0|
  1370. {
  1371. return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
  1372. }
  1373. template <class T>
  1374. inline
  1375. NSCAP_BOOL
  1376. operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1377. // specifically to allow |0 != smartPtr|
  1378. {
  1379. return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
  1380. }
  1381. #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
  1382. // We need to explicitly define comparison operators for `int'
  1383. // because the compiler is lame.
  1384. template <class T>
  1385. inline
  1386. NSCAP_BOOL
  1387. operator==( const nsCOMPtr<T>& lhs, int rhs )
  1388. // specifically to allow |smartPtr == 0|
  1389. {
  1390. return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
  1391. }
  1392. template <class T>
  1393. inline
  1394. NSCAP_BOOL
  1395. operator==( int lhs, const nsCOMPtr<T>& rhs )
  1396. // specifically to allow |0 == smartPtr|
  1397. {
  1398. return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
  1399. }
  1400. #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
  1401. // Comparing any two [XP]COM objects for identity
  1402. inline
  1403. NSCAP_BOOL
  1404. SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
  1405. {
  1406. return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
  1407. }
  1408. template <class SourceType, class DestinationType>
  1409. inline
  1410. nsresult
  1411. CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
  1412. {
  1413. return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  1414. }
  1415. #endif // !defined(nsCOMPtr_h___)