diff -r 000000000000 -r 6474c204b198 xpcom/glue/nsTWeakRef.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xpcom/glue/nsTWeakRef.h Wed Dec 31 06:09:35 2014 +0100
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsTWeakRef_h__
+#define nsTWeakRef_h__
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+/**
+ * A weak reference class for use with generic C++ objects. NOT THREADSAFE!
+ *
+ * Example usage:
+ *
+ * class A {
+ * public:
+ * A() : mWeakSelf(this) {
+ * }
+ * ~A() {
+ * mWeakSelf.forget();
+ * }
+ * void Bar() { printf("Bar!\n"); }
+ * const nsTWeakRef &AsWeakRef() const { return mWeakSelf; }
+ * private:
+ * nsTWeakRef mWeakSelf;
+ * };
+ *
+ * class B {
+ * public:
+ * void SetA(const nsTWeakRef &a) {
+ * mA = a;
+ * }
+ * void Foo() {
+ * if (mA)
+ * mA->Bar();
+ * }
+ * private:
+ * nsTWeakRef mA;
+ * };
+ *
+ * void Test() {
+ * B b;
+ * {
+ * A a;
+ * b.SetA(a.AsWeakRef());
+ * b.Foo(); // prints "Bar!"
+ * }
+ * b.Foo(); // prints nothing because |a| has already been destroyed
+ * }
+ *
+ * One can imagine much more complex examples, especially when asynchronous
+ * event processing is involved.
+ *
+ * Keep in mind that you should only ever need a class like this when you have
+ * multiple instances of B, such that it is not possible for A and B to simply
+ * have pointers to one another.
+ */
+template
+class nsTWeakRef {
+public:
+ ~nsTWeakRef() {
+ if (mRef)
+ mRef->Release();
+ }
+
+ /**
+ * Construct from an object pointer (may be null).
+ */
+ explicit
+ nsTWeakRef(Type *obj = nullptr) {
+ if (obj) {
+ mRef = new Inner(obj);
+ } else {
+ mRef = nullptr;
+ }
+ }
+
+ /**
+ * Construct from another weak reference object.
+ */
+ explicit
+ nsTWeakRef(const nsTWeakRef &other) : mRef(other.mRef) {
+ if (mRef)
+ mRef->AddRef();
+ }
+
+ /**
+ * Assign from an object pointer.
+ */
+ nsTWeakRef &operator=(Type *obj) {
+ if (mRef)
+ mRef->Release();
+ if (obj) {
+ mRef = new Inner(obj);
+ } else {
+ mRef = nullptr;
+ }
+ return *this;
+ }
+
+ /**
+ * Assign from another weak reference object.
+ */
+ nsTWeakRef &operator=(const nsTWeakRef &other) {
+ if (mRef)
+ mRef->Release();
+ mRef = other.mRef;
+ if (mRef)
+ mRef->AddRef();
+ return *this;
+ }
+
+ /**
+ * Get the referenced object. This method may return null if the reference
+ * has been cleared or if an out-of-memory error occurred at assignment.
+ */
+ Type *get() const {
+ return mRef ? mRef->mObj : nullptr;
+ }
+
+ /**
+ * Called to "null out" the weak reference. Typically, the object referenced
+ * by this weak reference calls this method when it is being destroyed.
+ * @returns The former referenced object.
+ */
+ Type *forget() {
+ Type *obj;
+ if (mRef) {
+ obj = mRef->mObj;
+ mRef->mObj = nullptr;
+ mRef->Release();
+ mRef = nullptr;
+ } else {
+ obj = nullptr;
+ }
+ return obj;
+ }
+
+ /**
+ * Allow |*this| to be treated as a |Type*| for convenience.
+ */
+ operator Type *() const {
+ return get();
+ }
+
+ /**
+ * Allow |*this| to be treated as a |Type*| for convenience. Use with
+ * caution since this method will crash if the referenced object is null.
+ */
+ Type *operator->() const {
+ NS_ASSERTION(mRef && mRef->mObj,
+ "You can't dereference a null weak reference with operator->().");
+ return get();
+ }
+
+private:
+
+ struct Inner {
+ int mCnt;
+ Type *mObj;
+
+ Inner(Type *obj) : mCnt(1), mObj(obj) {}
+ void AddRef() { ++mCnt; }
+ void Release() { if (--mCnt == 0) delete this; }
+ };
+
+ Inner *mRef;
+};
+
+#endif // nsTWeakRef_h__