Bug 944176: Implement move construction and move assignment for mozilla::Scoped derivatives. r=waldo
authorJim Blandy <jimb@mozilla.com>
Thu, 27 Mar 2014 09:52:48 -0700
changeset 175662 012fea76225f8aae6806b1ef3aa2353041a0382c
parent 175661 a673af0b3f228fab7c8053e14a3ffa57189314cb
child 175663 e04599ab2ee3c149b49e48a716a502b54f6ba1c9
push id26496
push userkwierso@gmail.com
push dateFri, 28 Mar 2014 02:28:34 +0000
treeherdermozilla-central@3c09159e01da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo
bugs944176
milestone31.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 944176: Implement move construction and move assignment for mozilla::Scoped derivatives. r=waldo
mfbt/Scoped.h
--- a/mfbt/Scoped.h
+++ b/mfbt/Scoped.h
@@ -47,18 +47,20 @@
  *
  * In addition, this header provides class |Scoped| and macros |SCOPED_TEMPLATE|
  * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE|  to simplify the definition
  * of RAII classes for other scenarios. These macros have been used to
  * automatically close file descriptors/file handles when reaching the end of
  * the scope, graphics contexts, etc.
  */
 
+#include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
+#include "mozilla/Move.h"
 #include "mozilla/NullPtr.h"
 
 namespace mozilla {
 
 /*
  * Scoped is a helper to create RAII wrappers
  * Type argument |Traits| is expected to have the following structure:
  *
@@ -78,22 +80,33 @@ class Scoped
   public:
     typedef typename Traits::type Resource;
 
     explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
       : value(Traits::empty())
     {
       MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
+
     explicit Scoped(const Resource& v
                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : value(v)
     {
       MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
+
+    /* Move constructor. */
+    explicit Scoped(Scoped&& v
+                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+      : value(Move(v.value))
+    {
+      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+      v.value = Traits::empty();
+    }
+
     ~Scoped() {
       Traits::release(value);
     }
 
     // Constant getter
     operator const Resource&() const { return value; }
     const Resource& operator->() const { return value; }
     const Resource& get() const { return value; }
@@ -141,16 +154,24 @@ class Scoped
       return reset(other);
     }
     Scoped& reset(const Resource& other) {
       Traits::release(value);
       value = other;
       return *this;
     }
 
+    /* Move assignment operator. */
+    Scoped& operator=(Scoped&& rhs) {
+      MOZ_ASSERT(&rhs != this, "self-move-assignment not allowed");
+      this->~Scoped();
+      new(this) Scoped(Move(rhs));
+      return *this;
+    }
+
   private:
     explicit Scoped(const Scoped& value) MOZ_DELETE;
     Scoped& operator=(const Scoped& value) MOZ_DELETE;
 
   private:
     Resource value;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
@@ -164,30 +185,40 @@ class Scoped
  * for more details.
  */
 #define SCOPED_TEMPLATE(name, Traits)                          \
 template<typename Type>                                        \
 struct name : public mozilla::Scoped<Traits<Type> >            \
 {                                                              \
     typedef mozilla::Scoped<Traits<Type> > Super;              \
     typedef typename Super::Resource Resource;                 \
-    name& operator=(Resource ptr) {                            \
-      Super::operator=(ptr);                                   \
+    name& operator=(Resource rhs) {                            \
+      Super::operator=(rhs);                                   \
+      return *this;                                            \
+    }                                                          \
+    name& operator=(name&& rhs) {                              \
+      Super::operator=(Move(rhs));                             \
       return *this;                                            \
     }                                                          \
     explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)        \
       : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)  \
     {}                                                         \
-    explicit name(Resource ptr                                 \
+    explicit name(Resource rhs                                 \
                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)             \
-      : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)   \
+      : Super(rhs                                              \
+              MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)       \
+    {}                                                         \
+    explicit name(name&& rhs                                   \
+                  MOZ_GUARD_OBJECT_NOTIFIER_PARAM)             \
+      : Super(Move(rhs)                                        \
+              MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)       \
     {}                                                         \
   private:                                                     \
-    explicit name(name& source) MOZ_DELETE;                    \
-    name& operator=(name& source) MOZ_DELETE;                  \
+    explicit name(name&) MOZ_DELETE;                           \
+    name& operator=(name&) MOZ_DELETE;                         \
 };
 
 /*
  * ScopedFreePtr is a RAII wrapper for pointers that need to be free()d.
  *
  *   struct S { ... };
  *   ScopedFreePtr<S> foo = malloc(sizeof(S));
  *   ScopedFreePtr<char> bar = strdup(str);