Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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__ |