/gecko_api/include/nsTWeakRef.h

http://firefox-mac-pdf.googlecode.com/ · C Header · 206 lines · 77 code · 16 blank · 113 comment · 14 complexity · baa385aa4895827c08f6e84104ac394f MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim:set ts=2 sw=2 sts=2 et cindent: */
  3. /* ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is Mozilla code.
  17. *
  18. * The Initial Developer of the Original Code is Google Inc.
  19. * Portions created by the Initial Developer are Copyright (C) 2006
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Darin Fisher <darin@meer.net>
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. #ifndef nsTWeakRef_h__
  39. #define nsTWeakRef_h__
  40. #ifndef nsDebug_h___
  41. #include "nsDebug.h"
  42. #endif
  43. /**
  44. * A weak reference class for use with generic C++ objects. NOT THREADSAFE!
  45. *
  46. * Example usage:
  47. *
  48. * class A {
  49. * public:
  50. * A() : mWeakSelf(this) {
  51. * }
  52. * ~A() {
  53. * mWeakSelf.forget();
  54. * }
  55. * void Bar() { printf("Bar!\n"); }
  56. * const nsTWeakRef<A> &AsWeakRef() const { return mWeakSelf; }
  57. * private:
  58. * nsTWeakRef<A> mWeakSelf;
  59. * };
  60. *
  61. * class B {
  62. * public:
  63. * void SetA(const nsTWeakRef<A> &a) {
  64. * mA = a;
  65. * }
  66. * void Foo() {
  67. * if (mA)
  68. * mA->Bar();
  69. * }
  70. * private:
  71. * nsTWeakRef<A> mA;
  72. * };
  73. *
  74. * void Test() {
  75. * B b;
  76. * {
  77. * A a;
  78. * b.SetA(a.AsWeakRef());
  79. * b.Foo(); // prints "Bar!"
  80. * }
  81. * b.Foo(); // prints nothing because |a| has already been destroyed
  82. * }
  83. *
  84. * One can imagine much more complex examples, especially when asynchronous
  85. * event processing is involved.
  86. *
  87. * Keep in mind that you should only ever need a class like this when you have
  88. * multiple instances of B, such that it is not possible for A and B to simply
  89. * have pointers to one another.
  90. */
  91. template <class Type>
  92. class nsTWeakRef {
  93. public:
  94. ~nsTWeakRef() {
  95. if (mRef)
  96. mRef->Release();
  97. }
  98. /**
  99. * Construct from an object pointer (may be null).
  100. */
  101. explicit
  102. nsTWeakRef(Type *obj = nsnull) {
  103. if (obj) {
  104. mRef = new Inner(obj);
  105. } else {
  106. mRef = nsnull;
  107. }
  108. }
  109. /**
  110. * Construct from another weak reference object.
  111. */
  112. explicit
  113. nsTWeakRef(const nsTWeakRef<Type> &other) : mRef(other.mRef) {
  114. if (mRef)
  115. mRef->AddRef();
  116. }
  117. /**
  118. * Assign from an object pointer.
  119. */
  120. nsTWeakRef<Type> &operator=(Type *obj) {
  121. if (mRef)
  122. mRef->Release();
  123. if (obj) {
  124. mRef = new Inner(obj);
  125. } else {
  126. mRef = nsnull;
  127. }
  128. return *this;
  129. }
  130. /**
  131. * Assign from another weak reference object.
  132. */
  133. nsTWeakRef<Type> &operator=(const nsTWeakRef<Type> &other) {
  134. if (mRef)
  135. mRef->Release();
  136. mRef = other.mRef;
  137. if (mRef)
  138. mRef->AddRef();
  139. return *this;
  140. }
  141. /**
  142. * Get the referenced object. This method may return null if the reference
  143. * has been cleared or if an out-of-memory error occured at assignment.
  144. */
  145. Type *get() const {
  146. return mRef ? mRef->mObj : nsnull;
  147. }
  148. /**
  149. * Called to "null out" the weak reference. Typically, the object referenced
  150. * by this weak reference calls this method when it is being destroyed.
  151. * @returns The former referenced object.
  152. */
  153. Type *forget() {
  154. Type *obj;
  155. if (mRef) {
  156. obj = mRef->mObj;
  157. mRef->mObj = nsnull;
  158. mRef->Release();
  159. mRef = nsnull;
  160. } else {
  161. obj = nsnull;
  162. }
  163. return obj;
  164. }
  165. /**
  166. * Allow |*this| to be treated as a |Type*| for convenience.
  167. */
  168. operator Type *() const {
  169. return get();
  170. }
  171. /**
  172. * Allow |*this| to be treated as a |Type*| for convenience. Use with
  173. * caution since this method will crash if the referenced object is null.
  174. */
  175. Type *operator->() const {
  176. NS_ASSERTION(mRef && mRef->mObj,
  177. "You can't dereference a null weak reference with operator->().");
  178. return get();
  179. }
  180. private:
  181. struct Inner {
  182. int mCnt;
  183. Type *mObj;
  184. Inner(Type *obj) : mCnt(1), mObj(obj) {}
  185. void AddRef() { ++mCnt; }
  186. void Release() { if (--mCnt == 0) delete this; }
  187. };
  188. Inner *mRef;
  189. };
  190. #endif // nsTWeakRef_h__