xpcom/glue/nsTWeakRef.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial