1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsTWeakRef.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,174 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsTWeakRef_h__ 1.11 +#define nsTWeakRef_h__ 1.12 + 1.13 +#ifndef nsDebug_h___ 1.14 +#include "nsDebug.h" 1.15 +#endif 1.16 + 1.17 +/** 1.18 + * A weak reference class for use with generic C++ objects. NOT THREADSAFE! 1.19 + * 1.20 + * Example usage: 1.21 + * 1.22 + * class A { 1.23 + * public: 1.24 + * A() : mWeakSelf(this) { 1.25 + * } 1.26 + * ~A() { 1.27 + * mWeakSelf.forget(); 1.28 + * } 1.29 + * void Bar() { printf("Bar!\n"); } 1.30 + * const nsTWeakRef<A> &AsWeakRef() const { return mWeakSelf; } 1.31 + * private: 1.32 + * nsTWeakRef<A> mWeakSelf; 1.33 + * }; 1.34 + * 1.35 + * class B { 1.36 + * public: 1.37 + * void SetA(const nsTWeakRef<A> &a) { 1.38 + * mA = a; 1.39 + * } 1.40 + * void Foo() { 1.41 + * if (mA) 1.42 + * mA->Bar(); 1.43 + * } 1.44 + * private: 1.45 + * nsTWeakRef<A> mA; 1.46 + * }; 1.47 + * 1.48 + * void Test() { 1.49 + * B b; 1.50 + * { 1.51 + * A a; 1.52 + * b.SetA(a.AsWeakRef()); 1.53 + * b.Foo(); // prints "Bar!" 1.54 + * } 1.55 + * b.Foo(); // prints nothing because |a| has already been destroyed 1.56 + * } 1.57 + * 1.58 + * One can imagine much more complex examples, especially when asynchronous 1.59 + * event processing is involved. 1.60 + * 1.61 + * Keep in mind that you should only ever need a class like this when you have 1.62 + * multiple instances of B, such that it is not possible for A and B to simply 1.63 + * have pointers to one another. 1.64 + */ 1.65 +template <class Type> 1.66 +class nsTWeakRef { 1.67 +public: 1.68 + ~nsTWeakRef() { 1.69 + if (mRef) 1.70 + mRef->Release(); 1.71 + } 1.72 + 1.73 + /** 1.74 + * Construct from an object pointer (may be null). 1.75 + */ 1.76 + explicit 1.77 + nsTWeakRef(Type *obj = nullptr) { 1.78 + if (obj) { 1.79 + mRef = new Inner(obj); 1.80 + } else { 1.81 + mRef = nullptr; 1.82 + } 1.83 + } 1.84 + 1.85 + /** 1.86 + * Construct from another weak reference object. 1.87 + */ 1.88 + explicit 1.89 + nsTWeakRef(const nsTWeakRef<Type> &other) : mRef(other.mRef) { 1.90 + if (mRef) 1.91 + mRef->AddRef(); 1.92 + } 1.93 + 1.94 + /** 1.95 + * Assign from an object pointer. 1.96 + */ 1.97 + nsTWeakRef<Type> &operator=(Type *obj) { 1.98 + if (mRef) 1.99 + mRef->Release(); 1.100 + if (obj) { 1.101 + mRef = new Inner(obj); 1.102 + } else { 1.103 + mRef = nullptr; 1.104 + } 1.105 + return *this; 1.106 + } 1.107 + 1.108 + /** 1.109 + * Assign from another weak reference object. 1.110 + */ 1.111 + nsTWeakRef<Type> &operator=(const nsTWeakRef<Type> &other) { 1.112 + if (mRef) 1.113 + mRef->Release(); 1.114 + mRef = other.mRef; 1.115 + if (mRef) 1.116 + mRef->AddRef(); 1.117 + return *this; 1.118 + } 1.119 + 1.120 + /** 1.121 + * Get the referenced object. This method may return null if the reference 1.122 + * has been cleared or if an out-of-memory error occurred at assignment. 1.123 + */ 1.124 + Type *get() const { 1.125 + return mRef ? mRef->mObj : nullptr; 1.126 + } 1.127 + 1.128 + /** 1.129 + * Called to "null out" the weak reference. Typically, the object referenced 1.130 + * by this weak reference calls this method when it is being destroyed. 1.131 + * @returns The former referenced object. 1.132 + */ 1.133 + Type *forget() { 1.134 + Type *obj; 1.135 + if (mRef) { 1.136 + obj = mRef->mObj; 1.137 + mRef->mObj = nullptr; 1.138 + mRef->Release(); 1.139 + mRef = nullptr; 1.140 + } else { 1.141 + obj = nullptr; 1.142 + } 1.143 + return obj; 1.144 + } 1.145 + 1.146 + /** 1.147 + * Allow |*this| to be treated as a |Type*| for convenience. 1.148 + */ 1.149 + operator Type *() const { 1.150 + return get(); 1.151 + } 1.152 + 1.153 + /** 1.154 + * Allow |*this| to be treated as a |Type*| for convenience. Use with 1.155 + * caution since this method will crash if the referenced object is null. 1.156 + */ 1.157 + Type *operator->() const { 1.158 + NS_ASSERTION(mRef && mRef->mObj, 1.159 + "You can't dereference a null weak reference with operator->()."); 1.160 + return get(); 1.161 + } 1.162 + 1.163 +private: 1.164 + 1.165 + struct Inner { 1.166 + int mCnt; 1.167 + Type *mObj; 1.168 + 1.169 + Inner(Type *obj) : mCnt(1), mObj(obj) {} 1.170 + void AddRef() { ++mCnt; } 1.171 + void Release() { if (--mCnt == 0) delete this; } 1.172 + }; 1.173 + 1.174 + Inner *mRef; 1.175 +}; 1.176 + 1.177 +#endif // nsTWeakRef_h__