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