Bug 1363676. P1 - use Variant as the internal storage of ResolveOrRejectValue. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 09 May 2017 18:24:18 +0800
changeset 575347 03c098991e9614434525ae133a051fd5964d6758
parent 575315 fc6a2748dcd08000a22693799d097ba6ca0eb0ce
child 575348 d328237d65d674e1567a7f726a212ad6d5e0f75a
push id58038
push userjwwang@mozilla.com
push dateWed, 10 May 2017 10:03:39 +0000
bugs1363676
milestone55.0a1
Bug 1363676. P1 - use Variant as the internal storage of ResolveOrRejectValue. MozReview-Commit-ID: 4B3M3hvfvyz
xpcom/threads/MozPromise.h
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -10,16 +10,17 @@
 #include "mozilla/AbstractThread.h"
 #include "mozilla/IndexSequence.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/TypeTraits.h"
+#include "mozilla/Variant.h"
 
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 #if defined(DEBUG) || !defined(RELEASE_OR_BETA)
 #define PROMISE_DEBUG
 #endif
 
@@ -132,29 +133,42 @@ class MozPromise : public MozPromiseRefc
 {
   static const uint32_t sMagic = 0xcecace11;
 
 public:
   typedef ResolveValueT ResolveValueType;
   typedef RejectValueT RejectValueType;
   class ResolveOrRejectValue
   {
+    template <int, typename T>
+    struct Holder
+    {
+      template <typename... Args>
+      explicit Holder(Args&&... aArgs) : mData(Forward<Args>(aArgs)...) { }
+      T mData;
+    };
+
+    // Ensure Holder<0, T1> and Holder<1, T2> are different types
+    // which is required by Variant.
+    using ResolveValueHolder = Holder<0, ResolveValueType>;
+    using RejectValueHolder = Holder<1, RejectValueType>;
+
   public:
     template<typename ResolveValueType_>
     void SetResolve(ResolveValueType_&& aResolveValue)
     {
       MOZ_ASSERT(IsNothing());
-      mResolveValue.emplace(Forward<ResolveValueType_>(aResolveValue));
+      mValue = AsVariant(ResolveValueHolder(Forward<ResolveValueType_>(aResolveValue)));
     }
 
     template<typename RejectValueType_>
     void SetReject(RejectValueType_&& aRejectValue)
     {
       MOZ_ASSERT(IsNothing());
-      mRejectValue.emplace(Forward<RejectValueType_>(aRejectValue));
+      mValue = AsVariant(RejectValueHolder(Forward<RejectValueType_>(aRejectValue)));
     }
 
     template<typename ResolveValueType_>
     static ResolveOrRejectValue MakeResolve(ResolveValueType_&& aResolveValue)
     {
       ResolveOrRejectValue val;
       val.SetResolve(Forward<ResolveValueType_>(aResolveValue));
       return val;
@@ -163,26 +177,39 @@ public:
     template<typename RejectValueType_>
     static ResolveOrRejectValue MakeReject(RejectValueType_&& aRejectValue)
     {
       ResolveOrRejectValue val;
       val.SetReject(Forward<RejectValueType_>(aRejectValue));
       return val;
     }
 
-    bool IsResolve() const { return mResolveValue.isSome(); }
-    bool IsReject() const { return mRejectValue.isSome(); }
-    bool IsNothing() const { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
+    bool IsResolve() const { return mValue.template is<ResolveValueHolder>(); }
+    bool IsReject() const { return mValue.template is<RejectValueHolder>(); }
+    bool IsNothing() const { return mValue.template is<Nothing>(); }
 
-    const ResolveValueType& ResolveValue() const { return mResolveValue.ref(); }
-    const RejectValueType& RejectValue() const { return mRejectValue.ref(); }
+    const ResolveValueType& ResolveValue() const
+    {
+      return mValue.template as<ResolveValueHolder>().mData;
+    }
+    ResolveValueType& ResolveValue()
+    {
+      return mValue.template as<ResolveValueHolder>().mData;
+    }
+    const RejectValueType& RejectValue() const
+    {
+      return mValue.template as<RejectValueHolder>().mData;
+    }
+    RejectValueType& RejectValue()
+    {
+      return mValue.template as<RejectValueHolder>().mData;
+    }
 
   private:
-    Maybe<ResolveValueType> mResolveValue;
-    Maybe<RejectValueType> mRejectValue;
+    Variant<Nothing, ResolveValueHolder, RejectValueHolder> mValue = AsVariant(Nothing{});
   };
 
 protected:
   // MozPromise is the public type, and never constructed directly. Construct
   // a MozPromise::Private, defined below.
   MozPromise(const char* aCreationSite, bool aIsCompletionPromise)
     : mCreationSite(aCreationSite)
     , mMutex("MozPromise Mutex")