diff --git a/mfbt/Function.h b/mfbt/Function.h index 1cc3a5622d6b..6a617e38314c 100644 --- a/mfbt/Function.h +++ b/mfbt/Function.h @@ -11,7 +11,8 @@ #include "mozilla/Attributes.h" // for MOZ_IMPLICIT #include "mozilla/Move.h" -#include "mozilla/UniquePtr.h" +#include "mozilla/RefCounted.h" +#include "mozilla/RefPtr.h" // |Function| is a wrapper that can hold any type of callable // object that can be invoked in a way that's compatible with |Signature|. @@ -40,9 +41,11 @@ namespace mozilla { namespace detail { template -class FunctionImplBase +class FunctionImplBase : public mozilla::RefCounted> { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FunctionImplBase) + virtual ~FunctionImplBase() {} virtual ReturnType call(Arguments... aArguments) = 0; }; @@ -137,7 +140,12 @@ public: // This constructor is implicit to match the interface of |std::function|. template MOZ_IMPLICIT Function(const Callable& aCallable) - : mImpl(MakeUnique>(aCallable)) + : mImpl(new detail::FunctionImpl(aCallable)) + {} + MOZ_IMPLICIT Function(const Function& aFunction) + : mImpl(aFunction.mImpl) + {} + MOZ_IMPLICIT Function(decltype(nullptr)) {} // Move constructor and move assingment operator. @@ -151,7 +159,17 @@ public: template Function& operator=(const Callable& aCallable) { - mImpl = MakeUnique>(aCallable); + mImpl = new detail::FunctionImpl(aCallable); + return *this; + } + Function& operator=(const Function& aFunction) + { + mImpl = aFunction.mImpl; + return *this; + } + Function& operator=(decltype(nullptr)) + { + mImpl = nullptr; return *this; } @@ -161,9 +179,15 @@ public: MOZ_ASSERT(mImpl); return mImpl->call(Forward(aArguments)...); } + + explicit operator bool() const + { + return bool(mImpl); + } + private: // TODO: Consider implementing a small object optimization. - UniquePtr> mImpl; + RefPtr> mImpl; }; } // namespace mozilla