Bug 1044668 - 2/2 - let WebGLFramebufferAttachable::AttachmentPoint use WeakPtr instead of a raw pointer - r=kamidphish
authorBenoit Jacob <bjacob@mozilla.com>
Wed, 30 Jul 2014 15:52:08 -0400
changeset 196944 79d249340b3ff3d1b1b0223e0c132718be1bb12d
parent 196943 621963c110239e77f03cf22ca5f158d362b709b3
child 196945 30b20d83771751123bb5b1935036a39ac11d5ed5
push id27228
push usercbook@mozilla.com
push dateThu, 31 Jul 2014 10:58:52 +0000
treeherdermozilla-central@aa176fcc56b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish
bugs1044668
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1044668 - 2/2 - let WebGLFramebufferAttachable::AttachmentPoint use WeakPtr instead of a raw pointer - r=kamidphish
mfbt/tests/TestWeakPtr.cpp
--- a/mfbt/tests/TestWeakPtr.cpp
+++ b/mfbt/tests/TestWeakPtr.cpp
@@ -9,70 +9,115 @@
 using mozilla::SupportsWeakPtr;
 using mozilla::WeakPtr;
 
 // To have a class C support weak pointers, inherit from SupportsWeakPtr<C>.
 class C : public SupportsWeakPtr<C>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(C)
+
   int mNum;
+
+  C()
+    : mNum(0)
+  {}
+
+  ~C()
+  {
+    // Setting mNum in the destructor allows us to test against use-after-free below
+    mNum = 0xDEAD;
+  }
+
   void act() {}
+
+  bool isConst() {
+    return false;
+  }
+
+  bool isConst() const {
+    return true;
+  }
 };
 
-static void
-Example()
+bool isConst(C*)
 {
-  C* ptr = new C();
-
-  // Get weak pointers to ptr. The first time asWeakPtr is called
-  // a reference counted WeakReference object is created that
-  // can live beyond the lifetime of 'ptr'. The WeakReference
-  // object will be notified of 'ptr's destruction.
-  WeakPtr<C> weak = ptr;
-  WeakPtr<C> other = ptr;
-
-  // Test a weak pointer for validity before using it.
-  if (weak) {
-    weak->mNum = 17;
-    weak->act();
-  }
-
-  // Destroying the underlying object clears weak pointers to it.
-  delete ptr;
-
-  MOZ_RELEASE_ASSERT(!weak, "Deleting |ptr| clears weak pointers to it.");
-  MOZ_RELEASE_ASSERT(!other, "Deleting |ptr| clears all weak pointers to it.");
+  return false;
 }
 
-struct A : public SupportsWeakPtr<A>
+bool isConst(const C*)
 {
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(A)
-  int mData;
-};
+  return true;
+}
 
 int
 main()
 {
-  A* a = new A;
+  C* c1 = new C;
+  MOZ_RELEASE_ASSERT(c1->mNum == 0);
+
+  // Get weak pointers to c1. The first time,
+  // a reference-counted WeakReference object is created that
+  // can live beyond the lifetime of 'c1'. The WeakReference
+  // object will be notified of 'c1's destruction.
+  WeakPtr<C> w1 = c1;
+  // Test a weak pointer for validity before using it.
+  MOZ_RELEASE_ASSERT(w1);
+  MOZ_RELEASE_ASSERT(w1 == c1);
+  w1->mNum = 1;
+  w1->act();
 
-  // a2 is unused to test the case when we haven't initialized
-  // the internal WeakReference pointer.
-  A* a2 = new A;
+  // Test taking another WeakPtr<C> to c1
+  WeakPtr<C> w2 = c1;
+  MOZ_RELEASE_ASSERT(w2);
+  MOZ_RELEASE_ASSERT(w2 == c1);
+  MOZ_RELEASE_ASSERT(w2 == w1);
+  MOZ_RELEASE_ASSERT(w2->mNum == 1);
 
-  a->mData = 5;
-  WeakPtr<A> ptr = a;
+  // Test a WeakPtr<const C>
+  WeakPtr<const C> w3const = c1;
+  MOZ_RELEASE_ASSERT(w3const);
+  MOZ_RELEASE_ASSERT(w3const == c1);
+  MOZ_RELEASE_ASSERT(w3const == w1);
+  MOZ_RELEASE_ASSERT(w3const == w2);
+  MOZ_RELEASE_ASSERT(w3const->mNum == 1);
+
+  // Test const-correctness of operator-> and operator T*
+  MOZ_RELEASE_ASSERT(!w1->isConst());
+  MOZ_RELEASE_ASSERT(w3const->isConst());
+  MOZ_RELEASE_ASSERT(!isConst(w1));
+  MOZ_RELEASE_ASSERT(isConst(w3const));
+
+  // Test that when a WeakPtr is destroyed, it does not destroy the object that it points to,
+  // and it does not affect other WeakPtrs pointing to the same object (e.g. it does not
+  // destroy the WeakReference object).
   {
-    WeakPtr<A> ptr2 = a;
-    MOZ_RELEASE_ASSERT(ptr->mData == 5);
-    WeakPtr<A> ptr3 = a;
-    MOZ_RELEASE_ASSERT(ptr->mData == 5);
+    WeakPtr<C> w4local = c1;
+    MOZ_RELEASE_ASSERT(w4local == c1);
   }
+  // Now w4local has gone out of scope. If that had destroyed c1, then the following would fail
+  // for sure (see C::~C()).
+  MOZ_RELEASE_ASSERT(c1->mNum == 1);
+  // Check that w4local going out of scope hasn't affected other WeakPtr's pointing to c1
+  MOZ_RELEASE_ASSERT(w1 == c1);
+  MOZ_RELEASE_ASSERT(w2 == c1);
 
-  delete a;
-  MOZ_RELEASE_ASSERT(!ptr);
-
-  delete a2;
+  // Now construct another C object and test changing what object a WeakPtr points to
+  C* c2 = new C;
+  c2->mNum = 2;
+  MOZ_RELEASE_ASSERT(w2->mNum == 1); // w2 was pointing to c1
+  w2 = c2;
+  MOZ_RELEASE_ASSERT(w2);
+  MOZ_RELEASE_ASSERT(w2 == c2);
+  MOZ_RELEASE_ASSERT(w2 != c1);
+  MOZ_RELEASE_ASSERT(w2 != w1);
+  MOZ_RELEASE_ASSERT(w2->mNum == 2);
 
-  Example();
+  // Destroying the underlying object clears weak pointers to it.
+  // It should not affect pointers that are not currently pointing to it.
+  delete c1;
+  MOZ_RELEASE_ASSERT(!w1, "Deleting an object should clear WeakPtr's to it.");
+  MOZ_RELEASE_ASSERT(!w3const, "Deleting an object should clear WeakPtr's to it.");
+  MOZ_RELEASE_ASSERT(w2, "Deleting an object should not clear WeakPtr that are not pointing to it.");
 
-  return 0;
+  delete c2;
+  MOZ_RELEASE_ASSERT(!w2, "Deleting an object should clear WeakPtr's to it.");
 }