xpcom/glue/nsTWeakRef.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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.

     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/. */
     7 #ifndef nsTWeakRef_h__
     8 #define nsTWeakRef_h__
    10 #ifndef nsDebug_h___
    11 #include "nsDebug.h"
    12 #endif
    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   }
    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   }
    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   }
    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   }
   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   }
   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   }
   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   }
   143   /**
   144    * Allow |*this| to be treated as a |Type*| for convenience.
   145    */
   146   operator Type *() const {
   147     return get();
   148   }
   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   }
   160 private:
   162   struct Inner {
   163     int     mCnt;
   164     Type   *mObj;
   166     Inner(Type *obj) : mCnt(1), mObj(obj) {}
   167     void AddRef() { ++mCnt; }
   168     void Release() { if (--mCnt == 0) delete this; }
   169   };
   171   Inner *mRef;
   172 };
   174 #endif  // nsTWeakRef_h__

mercurial