nsCOMPtr.h 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649
  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 <[email protected]> (original author)
  24. * L. David Baron <[email protected]>
  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_IID| et al
  58. #endif
  59. #ifndef nscore_h___
  60. #include "nscore.h"
  61. // for |NS_..._CAST|, |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 soley 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 soley 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. 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. 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_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 <[email protected]> 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 = NS_REINTERPRET_CAST(T*, mRawPtr);
  679. mRawPtr = temp;
  680. NSCAP_ASSERT_NO_QUERY_NEEDED();
  681. }
  682. // Other pointer operators
  683. nsDerivedSafe<T>*
  684. get() const
  685. /*
  686. Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
  687. Use |get()| _only_ to resolve ambiguity.
  688. Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
  689. */
  690. {
  691. return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
  692. }
  693. operator nsDerivedSafe<T>*() const
  694. /*
  695. ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  696. and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
  697. that makes an |nsCOMPtr| substitutable for a raw pointer.
  698. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  699. */
  700. {
  701. return get();
  702. }
  703. nsDerivedSafe<T>*
  704. operator->() const
  705. {
  706. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  707. return get();
  708. }
  709. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  710. // broken version for IRIX
  711. nsCOMPtr<T>*
  712. get_address() const
  713. // This is not intended to be used by clients. See |address_of|
  714. // below.
  715. {
  716. return NS_CONST_CAST(nsCOMPtr<T>*, this);
  717. }
  718. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  719. nsCOMPtr<T>*
  720. get_address()
  721. // This is not intended to be used by clients. See |address_of|
  722. // below.
  723. {
  724. return this;
  725. }
  726. const nsCOMPtr<T>*
  727. get_address() const
  728. // This is not intended to be used by clients. See |address_of|
  729. // below.
  730. {
  731. return this;
  732. }
  733. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  734. public:
  735. nsDerivedSafe<T>&
  736. operator*() const
  737. {
  738. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  739. return *get();
  740. }
  741. #if 0
  742. private:
  743. friend class nsGetterAddRefs<T>;
  744. #endif
  745. T**
  746. StartAssignment()
  747. {
  748. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  749. return NS_REINTERPRET_CAST(T**, begin_assignment());
  750. #else
  751. assign_assuming_AddRef(0);
  752. return NS_REINTERPRET_CAST(T**, &mRawPtr);
  753. #endif
  754. }
  755. };
  756. /*
  757. Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
  758. same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
  759. to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
  760. to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
  761. querying ensues. Clients need to be able to pass around arbitrary interface pointers,
  762. without hassles, through intermediary code that doesn't know the exact type.
  763. */
  764. NS_SPECIALIZE_TEMPLATE
  765. class nsCOMPtr<nsISupports>
  766. : private nsCOMPtr_base
  767. {
  768. public:
  769. typedef nsISupports element_type;
  770. // Constructors
  771. nsCOMPtr()
  772. : nsCOMPtr_base(0)
  773. // default constructor
  774. {
  775. NSCAP_LOG_ASSIGNMENT(this, 0);
  776. }
  777. nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
  778. : nsCOMPtr_base(aSmartPtr.mRawPtr)
  779. // copy constructor
  780. {
  781. if ( mRawPtr )
  782. NSCAP_ADDREF(this, mRawPtr);
  783. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  784. }
  785. nsCOMPtr( nsISupports* aRawPtr )
  786. : nsCOMPtr_base(aRawPtr)
  787. // construct from a raw pointer (of the right type)
  788. {
  789. if ( mRawPtr )
  790. NSCAP_ADDREF(this, mRawPtr);
  791. NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  792. }
  793. nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
  794. : nsCOMPtr_base(aSmartPtr.mRawPtr)
  795. // construct from |dont_AddRef(expr)|
  796. {
  797. NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  798. }
  799. nsCOMPtr( const nsQueryInterface qi )
  800. : nsCOMPtr_base(0)
  801. // assign from |do_QueryInterface(expr)|
  802. {
  803. NSCAP_LOG_ASSIGNMENT(this, 0);
  804. assign_from_qi(qi, NS_GET_IID(nsISupports));
  805. }
  806. nsCOMPtr( const nsQueryInterfaceWithError& qi )
  807. : nsCOMPtr_base(0)
  808. // assign from |do_QueryInterface(expr, &rv)|
  809. {
  810. NSCAP_LOG_ASSIGNMENT(this, 0);
  811. assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
  812. }
  813. nsCOMPtr( const nsGetServiceByCID gs )
  814. : nsCOMPtr_base(0)
  815. // assign from |do_GetService(cid_expr)|
  816. {
  817. NSCAP_LOG_ASSIGNMENT(this, 0);
  818. assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
  819. }
  820. nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  821. : nsCOMPtr_base(0)
  822. // assign from |do_GetService(cid_expr, &rv)|
  823. {
  824. NSCAP_LOG_ASSIGNMENT(this, 0);
  825. assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
  826. }
  827. nsCOMPtr( const nsGetServiceByContractID gs )
  828. : nsCOMPtr_base(0)
  829. // assign from |do_GetService(contractid_expr)|
  830. {
  831. NSCAP_LOG_ASSIGNMENT(this, 0);
  832. assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
  833. }
  834. nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  835. : nsCOMPtr_base(0)
  836. // assign from |do_GetService(contractid_expr, &rv)|
  837. {
  838. NSCAP_LOG_ASSIGNMENT(this, 0);
  839. assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
  840. }
  841. nsCOMPtr( const nsCOMPtr_helper& helper )
  842. : nsCOMPtr_base(0)
  843. // ...and finally, anything else we might need to construct from
  844. // can exploit the |nsCOMPtr_helper| facility
  845. {
  846. NSCAP_LOG_ASSIGNMENT(this, 0);
  847. assign_from_helper(helper, NS_GET_IID(nsISupports));
  848. }
  849. // Assignment operators
  850. nsCOMPtr<nsISupports>&
  851. operator=( const nsCOMPtr<nsISupports>& rhs )
  852. // copy assignment operator
  853. {
  854. assign_with_AddRef(rhs.mRawPtr);
  855. return *this;
  856. }
  857. nsCOMPtr<nsISupports>&
  858. operator=( nsISupports* rhs )
  859. // assign from a raw pointer (of the right type)
  860. {
  861. assign_with_AddRef(rhs);
  862. return *this;
  863. }
  864. nsCOMPtr<nsISupports>&
  865. operator=( const already_AddRefed<nsISupports>& rhs )
  866. // assign from |dont_AddRef(expr)|
  867. {
  868. assign_assuming_AddRef(rhs.mRawPtr);
  869. return *this;
  870. }
  871. nsCOMPtr<nsISupports>&
  872. operator=( const nsQueryInterface rhs )
  873. // assign from |do_QueryInterface(expr)|
  874. {
  875. assign_from_qi(rhs, NS_GET_IID(nsISupports));
  876. return *this;
  877. }
  878. nsCOMPtr<nsISupports>&
  879. operator=( const nsQueryInterfaceWithError& rhs )
  880. // assign from |do_QueryInterface(expr, &rv)|
  881. {
  882. assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
  883. return *this;
  884. }
  885. nsCOMPtr<nsISupports>&
  886. operator=( const nsGetServiceByCID rhs )
  887. // assign from |do_GetService(cid_expr)|
  888. {
  889. assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
  890. return *this;
  891. }
  892. nsCOMPtr<nsISupports>&
  893. operator=( const nsGetServiceByCIDWithError& rhs )
  894. // assign from |do_GetService(cid_expr, &rv)|
  895. {
  896. assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
  897. return *this;
  898. }
  899. nsCOMPtr<nsISupports>&
  900. operator=( const nsGetServiceByContractID rhs )
  901. // assign from |do_GetService(contractid_expr)|
  902. {
  903. assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
  904. return *this;
  905. }
  906. nsCOMPtr<nsISupports>&
  907. operator=( const nsGetServiceByContractIDWithError& rhs )
  908. // assign from |do_GetService(contractid_expr, &rv)|
  909. {
  910. assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
  911. return *this;
  912. }
  913. nsCOMPtr<nsISupports>&
  914. operator=( const nsCOMPtr_helper& rhs )
  915. // ...and finally, anything else we might need to assign from
  916. // can exploit the |nsCOMPtr_helper| facility.
  917. {
  918. assign_from_helper(rhs, NS_GET_IID(nsISupports));
  919. return *this;
  920. }
  921. void
  922. swap( nsCOMPtr<nsISupports>& rhs )
  923. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  924. {
  925. nsISupports* temp = rhs.mRawPtr;
  926. NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  927. NSCAP_LOG_ASSIGNMENT(this, temp);
  928. NSCAP_LOG_RELEASE(this, mRawPtr);
  929. NSCAP_LOG_RELEASE(&rhs, temp);
  930. rhs.mRawPtr = mRawPtr;
  931. mRawPtr = temp;
  932. }
  933. void
  934. swap( nsISupports*& rhs )
  935. // ...exchange ownership with |rhs|; can save a pair of refcount operations
  936. {
  937. nsISupports* temp = rhs;
  938. NSCAP_LOG_ASSIGNMENT(this, temp);
  939. NSCAP_LOG_RELEASE(this, mRawPtr);
  940. rhs = mRawPtr;
  941. mRawPtr = temp;
  942. }
  943. // Other pointer operators
  944. nsDerivedSafe<nsISupports>*
  945. get() const
  946. /*
  947. Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
  948. Use |get()| _only_ to resolve ambiguity.
  949. Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
  950. */
  951. {
  952. return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
  953. }
  954. operator nsDerivedSafe<nsISupports>*() const
  955. /*
  956. ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  957. and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
  958. that makes an |nsCOMPtr| substitutable for a raw pointer.
  959. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  960. */
  961. {
  962. return get();
  963. }
  964. nsDerivedSafe<nsISupports>*
  965. operator->() const
  966. {
  967. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  968. return get();
  969. }
  970. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  971. // broken version for IRIX
  972. nsCOMPtr<nsISupports>*
  973. get_address() const
  974. // This is not intended to be used by clients. See |address_of|
  975. // below.
  976. {
  977. return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
  978. }
  979. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  980. nsCOMPtr<nsISupports>*
  981. get_address()
  982. // This is not intended to be used by clients. See |address_of|
  983. // below.
  984. {
  985. return this;
  986. }
  987. const nsCOMPtr<nsISupports>*
  988. get_address() const
  989. // This is not intended to be used by clients. See |address_of|
  990. // below.
  991. {
  992. return this;
  993. }
  994. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  995. public:
  996. nsDerivedSafe<nsISupports>&
  997. operator*() const
  998. {
  999. NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  1000. return *get();
  1001. }
  1002. #if 0
  1003. private:
  1004. friend class nsGetterAddRefs<nsISupports>;
  1005. #endif
  1006. nsISupports**
  1007. StartAssignment()
  1008. {
  1009. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  1010. return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
  1011. #else
  1012. assign_assuming_AddRef(0);
  1013. return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
  1014. #endif
  1015. }
  1016. };
  1017. #ifndef NSCAP_FEATURE_USE_BASE
  1018. template <class T>
  1019. void
  1020. nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
  1021. {
  1022. if ( rawPtr )
  1023. NSCAP_ADDREF(this, rawPtr);
  1024. assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
  1025. }
  1026. template <class T>
  1027. void
  1028. nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
  1029. {
  1030. T* newRawPtr;
  1031. if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1032. newRawPtr = 0;
  1033. assign_assuming_AddRef(newRawPtr);
  1034. }
  1035. template <class T>
  1036. void
  1037. nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
  1038. {
  1039. T* newRawPtr;
  1040. if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1041. newRawPtr = 0;
  1042. assign_assuming_AddRef(newRawPtr);
  1043. }
  1044. template <class T>
  1045. void
  1046. nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
  1047. {
  1048. T* newRawPtr;
  1049. if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1050. newRawPtr = 0;
  1051. assign_assuming_AddRef(newRawPtr);
  1052. }
  1053. template <class T>
  1054. void
  1055. nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
  1056. {
  1057. T* newRawPtr;
  1058. if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1059. newRawPtr = 0;
  1060. assign_assuming_AddRef(newRawPtr);
  1061. }
  1062. template <class T>
  1063. void
  1064. nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
  1065. {
  1066. T* newRawPtr;
  1067. if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1068. newRawPtr = 0;
  1069. assign_assuming_AddRef(newRawPtr);
  1070. }
  1071. template <class T>
  1072. void
  1073. nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
  1074. {
  1075. T* newRawPtr;
  1076. if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1077. newRawPtr = 0;
  1078. assign_assuming_AddRef(newRawPtr);
  1079. }
  1080. template <class T>
  1081. void
  1082. nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
  1083. {
  1084. T* newRawPtr;
  1085. if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1086. newRawPtr = 0;
  1087. assign_assuming_AddRef(newRawPtr);
  1088. }
  1089. template <class T>
  1090. void**
  1091. nsCOMPtr<T>::begin_assignment()
  1092. {
  1093. assign_assuming_AddRef(0);
  1094. return NS_REINTERPRET_CAST(void**, &mRawPtr);
  1095. }
  1096. #endif
  1097. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1098. // This is the broken version for IRIX, which can't handle the version below.
  1099. template <class T>
  1100. inline
  1101. nsCOMPtr<T>*
  1102. address_of( const nsCOMPtr<T>& aPtr )
  1103. {
  1104. return aPtr.get_address();
  1105. }
  1106. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1107. template <class T>
  1108. inline
  1109. nsCOMPtr<T>*
  1110. address_of( nsCOMPtr<T>& aPtr )
  1111. {
  1112. return aPtr.get_address();
  1113. }
  1114. template <class T>
  1115. inline
  1116. const nsCOMPtr<T>*
  1117. address_of( const nsCOMPtr<T>& aPtr )
  1118. {
  1119. return aPtr.get_address();
  1120. }
  1121. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1122. template <class T>
  1123. class nsGetterAddRefs
  1124. /*
  1125. ...
  1126. This class is designed to be used for anonymous temporary objects in the
  1127. argument list of calls that return COM interface pointers, e.g.,
  1128. nsCOMPtr<IFoo> fooP;
  1129. ...->QueryInterface(iid, getter_AddRefs(fooP))
  1130. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
  1131. When initialized with a |nsCOMPtr|, as in the example above, it returns
  1132. a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
  1133. case) can fill in.
  1134. This type should be a nested class inside |nsCOMPtr<T>|.
  1135. */
  1136. {
  1137. public:
  1138. explicit
  1139. nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
  1140. : mTargetSmartPtr(aSmartPtr)
  1141. {
  1142. // nothing else to do
  1143. }
  1144. #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
  1145. ~nsGetterAddRefs()
  1146. {
  1147. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1148. NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1149. #endif
  1150. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  1151. mTargetSmartPtr.Assert_NoQueryNeeded();
  1152. #endif
  1153. }
  1154. #endif
  1155. operator void**()
  1156. {
  1157. return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1158. }
  1159. operator nsISupports**()
  1160. {
  1161. return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
  1162. }
  1163. operator T**()
  1164. {
  1165. return mTargetSmartPtr.StartAssignment();
  1166. }
  1167. T*&
  1168. operator*()
  1169. {
  1170. return *(mTargetSmartPtr.StartAssignment());
  1171. }
  1172. private:
  1173. nsCOMPtr<T>& mTargetSmartPtr;
  1174. };
  1175. NS_SPECIALIZE_TEMPLATE
  1176. class nsGetterAddRefs<nsISupports>
  1177. {
  1178. public:
  1179. explicit
  1180. nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
  1181. : mTargetSmartPtr(aSmartPtr)
  1182. {
  1183. // nothing else to do
  1184. }
  1185. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1186. ~nsGetterAddRefs()
  1187. {
  1188. NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1189. }
  1190. #endif
  1191. operator void**()
  1192. {
  1193. return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1194. }
  1195. operator nsISupports**()
  1196. {
  1197. return mTargetSmartPtr.StartAssignment();
  1198. }
  1199. nsISupports*&
  1200. operator*()
  1201. {
  1202. return *(mTargetSmartPtr.StartAssignment());
  1203. }
  1204. private:
  1205. nsCOMPtr<nsISupports>& mTargetSmartPtr;
  1206. };
  1207. template <class T>
  1208. inline
  1209. nsGetterAddRefs<T>
  1210. getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
  1211. /*
  1212. Used around a |nsCOMPtr| when
  1213. ...makes the class |nsGetterAddRefs<T>| invisible.
  1214. */
  1215. {
  1216. return nsGetterAddRefs<T>(aSmartPtr);
  1217. }
  1218. // Comparing two |nsCOMPtr|s
  1219. template <class T, class U>
  1220. inline
  1221. NSCAP_BOOL
  1222. operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1223. {
  1224. return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
  1225. }
  1226. template <class T, class U>
  1227. inline
  1228. NSCAP_BOOL
  1229. operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1230. {
  1231. return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
  1232. }
  1233. // Comparing an |nsCOMPtr| to a raw pointer
  1234. template <class T, class U>
  1235. inline
  1236. NSCAP_BOOL
  1237. operator==( const nsCOMPtr<T>& lhs, const U* rhs )
  1238. {
  1239. return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
  1240. }
  1241. template <class T, class U>
  1242. inline
  1243. NSCAP_BOOL
  1244. operator==( const U* lhs, const nsCOMPtr<T>& rhs )
  1245. {
  1246. return lhs == NS_STATIC_CAST(const T*, rhs.get());
  1247. }
  1248. template <class T, class U>
  1249. inline
  1250. NSCAP_BOOL
  1251. operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
  1252. {
  1253. return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
  1254. }
  1255. template <class T, class U>
  1256. inline
  1257. NSCAP_BOOL
  1258. operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
  1259. {
  1260. return lhs != NS_STATIC_CAST(const T*, rhs.get());
  1261. }
  1262. // To avoid ambiguities caused by the presence of builtin |operator==|s
  1263. // creating a situation where one of the |operator==| defined above
  1264. // has a better conversion for one argument and the builtin has a
  1265. // better conversion for the other argument, define additional
  1266. // |operator==| without the |const| on the raw pointer.
  1267. // See bug 65664 for details.
  1268. // This is defined by an autoconf test, but VC++ also has a bug that
  1269. // prevents us from using these. (It also, fortunately, has the bug
  1270. // that we don't need them either.)
  1271. #if defined(_MSC_VER) && (_MSC_VER < 1310)
  1272. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1273. #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1274. #endif
  1275. #endif
  1276. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1277. template <class T, class U>
  1278. inline
  1279. NSCAP_BOOL
  1280. operator==( const nsCOMPtr<T>& lhs, U* rhs )
  1281. {
  1282. return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
  1283. }
  1284. template <class T, class U>
  1285. inline
  1286. NSCAP_BOOL
  1287. operator==( U* lhs, const nsCOMPtr<T>& rhs )
  1288. {
  1289. return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
  1290. }
  1291. template <class T, class U>
  1292. inline
  1293. NSCAP_BOOL
  1294. operator!=( const nsCOMPtr<T>& lhs, U* rhs )
  1295. {
  1296. return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
  1297. }
  1298. template <class T, class U>
  1299. inline
  1300. NSCAP_BOOL
  1301. operator!=( U* lhs, const nsCOMPtr<T>& rhs )
  1302. {
  1303. return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
  1304. }
  1305. #endif
  1306. // Comparing an |nsCOMPtr| to |0|
  1307. class NSCAP_Zero;
  1308. template <class T>
  1309. inline
  1310. NSCAP_BOOL
  1311. operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1312. // specifically to allow |smartPtr == 0|
  1313. {
  1314. return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1315. }
  1316. template <class T>
  1317. inline
  1318. NSCAP_BOOL
  1319. operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1320. // specifically to allow |0 == smartPtr|
  1321. {
  1322. return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1323. }
  1324. template <class T>
  1325. inline
  1326. NSCAP_BOOL
  1327. operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1328. // specifically to allow |smartPtr != 0|
  1329. {
  1330. return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
  1331. }
  1332. template <class T>
  1333. inline
  1334. NSCAP_BOOL
  1335. operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1336. // specifically to allow |0 != smartPtr|
  1337. {
  1338. return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
  1339. }
  1340. #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
  1341. // We need to explicitly define comparison operators for `int'
  1342. // because the compiler is lame.
  1343. template <class T>
  1344. inline
  1345. NSCAP_BOOL
  1346. operator==( const nsCOMPtr<T>& lhs, int rhs )
  1347. // specifically to allow |smartPtr == 0|
  1348. {
  1349. return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1350. }
  1351. template <class T>
  1352. inline
  1353. NSCAP_BOOL
  1354. operator==( int lhs, const nsCOMPtr<T>& rhs )
  1355. // specifically to allow |0 == smartPtr|
  1356. {
  1357. return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1358. }
  1359. #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
  1360. // Comparing any two [XP]COM objects for identity
  1361. inline
  1362. NSCAP_BOOL
  1363. SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
  1364. {
  1365. return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
  1366. }
  1367. template <class SourceType, class DestinationType>
  1368. inline
  1369. nsresult
  1370. CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
  1371. {
  1372. return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  1373. }
  1374. #endif // !defined(nsCOMPtr_h___)