xpcom/glue/nsTWeakRef.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:b86a6ecfdadc
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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef nsTWeakRef_h__
8 #define nsTWeakRef_h__
9
10 #ifndef nsDebug_h___
11 #include "nsDebug.h"
12 #endif
13
14 /**
15 * A weak reference class for use with generic C++ objects. NOT THREADSAFE!
16 *
17 * Example usage:
18 *
19 * class A {
20 * public:
21 * A() : mWeakSelf(this) {
22 * }
23 * ~A() {
24 * mWeakSelf.forget();
25 * }
26 * void Bar() { printf("Bar!\n"); }
27 * const nsTWeakRef<A> &AsWeakRef() const { return mWeakSelf; }
28 * private:
29 * nsTWeakRef<A> mWeakSelf;
30 * };
31 *
32 * class B {
33 * public:
34 * void SetA(const nsTWeakRef<A> &a) {
35 * mA = a;
36 * }
37 * void Foo() {
38 * if (mA)
39 * mA->Bar();
40 * }
41 * private:
42 * nsTWeakRef<A> mA;
43 * };
44 *
45 * void Test() {
46 * B b;
47 * {
48 * A a;
49 * b.SetA(a.AsWeakRef());
50 * b.Foo(); // prints "Bar!"
51 * }
52 * b.Foo(); // prints nothing because |a| has already been destroyed
53 * }
54 *
55 * One can imagine much more complex examples, especially when asynchronous
56 * event processing is involved.
57 *
58 * Keep in mind that you should only ever need a class like this when you have
59 * multiple instances of B, such that it is not possible for A and B to simply
60 * have pointers to one another.
61 */
62 template <class Type>
63 class nsTWeakRef {
64 public:
65 ~nsTWeakRef() {
66 if (mRef)
67 mRef->Release();
68 }
69
70 /**
71 * Construct from an object pointer (may be null).
72 */
73 explicit
74 nsTWeakRef(Type *obj = nullptr) {
75 if (obj) {
76 mRef = new Inner(obj);
77 } else {
78 mRef = nullptr;
79 }
80 }
81
82 /**
83 * Construct from another weak reference object.
84 */
85 explicit
86 nsTWeakRef(const nsTWeakRef<Type> &other) : mRef(other.mRef) {
87 if (mRef)
88 mRef->AddRef();
89 }
90
91 /**
92 * Assign from an object pointer.
93 */
94 nsTWeakRef<Type> &operator=(Type *obj) {
95 if (mRef)
96 mRef->Release();
97 if (obj) {
98 mRef = new Inner(obj);
99 } else {
100 mRef = nullptr;
101 }
102 return *this;
103 }
104
105 /**
106 * Assign from another weak reference object.
107 */
108 nsTWeakRef<Type> &operator=(const nsTWeakRef<Type> &other) {
109 if (mRef)
110 mRef->Release();
111 mRef = other.mRef;
112 if (mRef)
113 mRef->AddRef();
114 return *this;
115 }
116
117 /**
118 * Get the referenced object. This method may return null if the reference
119 * has been cleared or if an out-of-memory error occurred at assignment.
120 */
121 Type *get() const {
122 return mRef ? mRef->mObj : nullptr;
123 }
124
125 /**
126 * Called to "null out" the weak reference. Typically, the object referenced
127 * by this weak reference calls this method when it is being destroyed.
128 * @returns The former referenced object.
129 */
130 Type *forget() {
131 Type *obj;
132 if (mRef) {
133 obj = mRef->mObj;
134 mRef->mObj = nullptr;
135 mRef->Release();
136 mRef = nullptr;
137 } else {
138 obj = nullptr;
139 }
140 return obj;
141 }
142
143 /**
144 * Allow |*this| to be treated as a |Type*| for convenience.
145 */
146 operator Type *() const {
147 return get();
148 }
149
150 /**
151 * Allow |*this| to be treated as a |Type*| for convenience. Use with
152 * caution since this method will crash if the referenced object is null.
153 */
154 Type *operator->() const {
155 NS_ASSERTION(mRef && mRef->mObj,
156 "You can't dereference a null weak reference with operator->().");
157 return get();
158 }
159
160 private:
161
162 struct Inner {
163 int mCnt;
164 Type *mObj;
165
166 Inner(Type *obj) : mCnt(1), mObj(obj) {}
167 void AddRef() { ++mCnt; }
168 void Release() { if (--mCnt == 0) delete this; }
169 };
170
171 Inner *mRef;
172 };
173
174 #endif // nsTWeakRef_h__

mercurial