Bug 1116906 - Move AlreadyAddRefed.h to MFBT; r=froydnj
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 31 Dec 2014 11:42:05 -0500
changeset 248343 a194a9a118f1fa7b60937cf36e9234bdc9474f22
parent 248342 277f764e87ae6c77c7d50d6a9419438dc8e056be
child 248344 175c011226e3326758cd8728d09f3d199f75b27a
push idunknown
push userunknown
push dateunknown
reviewersfroydnj
bugs1116906
milestone37.0a1
Bug 1116906 - Move AlreadyAddRefed.h to MFBT; r=froydnj
mfbt/AlreadyAddRefed.h
mfbt/moz.build
xpcom/base/AlreadyAddRefed.h
xpcom/base/moz.build
xpcom/base/nsRefPtr.h
xpcom/glue/nsCOMPtr.h
new file mode 100644
--- /dev/null
+++ b/mfbt/AlreadyAddRefed.h
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Typed temporary pointers for reference-counted smart pointers. */
+
+#ifndef AlreadyAddRefed_h
+#define AlreadyAddRefed_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/NullPtr.h"
+
+namespace mozilla {
+
+struct unused_t;
+
+} // namespace mozilla
+
+/**
+ * already_AddRefed cooperates with reference counting smart pointers to enable
+ * you to assign in a pointer _without_ |AddRef|ing it.  You might want to use
+ * this as a return type from a function that returns an already |AddRef|ed
+ * pointer.
+ *
+ * TODO Move already_AddRefed to namespace mozilla.  This has not yet been done
+ * because of the sheer number of usages of already_AddRefed.
+ */
+template<class T>
+struct already_AddRefed
+{
+  /*
+   * We want to allow returning nullptr from functions returning
+   * already_AddRefed<T>, for simplicity.  But we also don't want to allow
+   * returning raw T*, instead preferring creation of already_AddRefed<T> from
+   * a reference counting smart pointer.
+   *
+   * We address the latter requirement by making the (T*) constructor explicit.
+   * But |return nullptr| won't consider an explicit constructor, so we need
+   * another constructor to handle it.  Plain old (decltype(nullptr)) doesn't
+   * cut it, because if nullptr is emulated as __null (with type int or long),
+   * passing nullptr to an int/long parameter triggers compiler warnings.  We
+   * need a type that no one can pass accidentally; a pointer-to-member-function
+   * (where no such function exists) does the trick nicely.
+   *
+   * That handles the return-value case.  What about for locals, argument types,
+   * and so on?  |already_AddRefed<T>(nullptr)| considers both overloads (and
+   * the (already_AddRefed<T>&&) overload as well!), so there's an ambiguity.
+   * We can target true nullptr using decltype(nullptr), but we can't target
+   * emulated nullptr the same way, because passing __null to an int/long
+   * parameter triggers compiler warnings.  So just give up on this, and provide
+   * this behavior through the default constructor.
+   *
+   * We can revert to simply explicit (T*) and implicit (decltype(nullptr)) when
+   * nullptr no longer needs to be emulated to support the ancient b2g compiler.
+   * (The () overload could also be removed, if desired, if we changed callers.)
+   */
+  already_AddRefed() : mRawPtr(nullptr) {}
+
+  // The return and argument types here are arbitrarily selected so no
+  // corresponding member function exists.
+  typedef void (already_AddRefed::* MatchNullptr)(double, float);
+  MOZ_IMPLICIT already_AddRefed(MatchNullptr aRawPtr) : mRawPtr(nullptr) {}
+
+  explicit already_AddRefed(T* aRawPtr) : mRawPtr(aRawPtr) {}
+
+  // Disallowed. Use move semantics instead.
+  already_AddRefed(const already_AddRefed<T>& aOther) MOZ_DELETE;
+
+  already_AddRefed(already_AddRefed<T>&& aOther) : mRawPtr(aOther.take()) {}
+
+  ~already_AddRefed() { MOZ_ASSERT(!mRawPtr); }
+
+  // Specialize the unused operator<< for already_AddRefed, to allow
+  // nsCOMPtr<nsIFoo> foo;
+  // unused << foo.forget();
+  // Note that nsCOMPtr is the XPCOM reference counting smart pointer class.
+  friend void operator<<(const mozilla::unused_t& aUnused,
+                         const already_AddRefed<T>& aRhs)
+  {
+    auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&aRhs);
+    aUnused << mutableAlreadyAddRefed->take();
+  }
+
+  MOZ_WARN_UNUSED_RESULT T* take()
+  {
+    T* rawPtr = mRawPtr;
+    mRawPtr = nullptr;
+    return rawPtr;
+  }
+
+  /**
+   * This helper is useful in cases like
+   *
+   *  already_AddRefed<BaseClass>
+   *  Foo()
+   *  {
+   *    nsRefPtr<SubClass> x = ...;
+   *    return x.forget();
+   *  }
+   *
+   * The autoconversion allows one to omit the idiom
+   *
+   *    nsRefPtr<BaseClass> y = x.forget();
+   *    return y.forget();
+   *
+   * Note that nsRefPtr is the XPCOM reference counting smart pointer class.
+   */
+  template<class U>
+  operator already_AddRefed<U>()
+  {
+    U* tmp = mRawPtr;
+    mRawPtr = nullptr;
+    return already_AddRefed<U>(tmp);
+  }
+
+  /**
+   * This helper provides a static_cast replacement for already_AddRefed, so
+   * if you have
+   *
+   *   already_AddRefed<Parent> F();
+   *
+   * you can write
+   *
+   *   already_AddRefed<Child>
+   *   G()
+   *   {
+   *     return F().downcast<Child>();
+   *   }
+   */
+  template<class U>
+  already_AddRefed<U> downcast()
+  {
+    U* tmp = static_cast<U*>(mRawPtr);
+    mRawPtr = nullptr;
+    return already_AddRefed<U>(tmp);
+  }
+
+private:
+  T* MOZ_OWNING_REF mRawPtr;
+};
+
+#endif // AlreadyAddRefed_h
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -6,16 +6,17 @@
 
 TEST_DIRS += ['tests']
 
 Library('mfbt')
 
 EXPORTS.mozilla = [
     'Alignment.h',
     'AllocPolicy.h',
+    'AlreadyAddRefed.h',
     'Array.h',
     'ArrayUtils.h',
     'Assertions.h',
     'Atomics.h',
     'Attributes.h',
     'BinarySearch.h',
     'BloomFilter.h',
     'Casting.h',
deleted file mode 100644
--- a/xpcom/base/AlreadyAddRefed.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Typed temporary pointers for reference-counted smart pointers. */
-
-#ifndef AlreadyAddRefed_h
-#define AlreadyAddRefed_h
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Move.h"
-#include "mozilla/NullPtr.h"
-
-namespace mozilla {
-
-struct unused_t;
-
-} // namespace mozilla
-
-/**
- * already_AddRefed cooperaters with nsCOMPtr/nsRefPtr to enable you to assign
- * in a pointer _without_ |AddRef|ing it.  You might want to use this as a
- * return type from a function that returns an already |AddRef|ed pointer.
- */
-template<class T>
-struct already_AddRefed
-{
-  /*
-   * We want to allow returning nullptr from functions returning
-   * already_AddRefed<T>, for simplicity.  But we also don't want to allow
-   * returning raw T*, instead preferring creation of already_AddRefed<T> from
-   * an nsRefPtr, nsCOMPtr, or the like.
-   *
-   * We address the latter requirement by making the (T*) constructor explicit.
-   * But |return nullptr| won't consider an explicit constructor, so we need
-   * another constructor to handle it.  Plain old (decltype(nullptr)) doesn't
-   * cut it, because if nullptr is emulated as __null (with type int or long),
-   * passing nullptr to an int/long parameter triggers compiler warnings.  We
-   * need a type that no one can pass accidentally; a pointer-to-member-function
-   * (where no such function exists) does the trick nicely.
-   *
-   * That handles the return-value case.  What about for locals, argument types,
-   * and so on?  |already_AddRefed<T>(nullptr)| considers both overloads (and
-   * the (already_AddRefed<T>&&) overload as well!), so there's an ambiguity.
-   * We can target true nullptr using decltype(nullptr), but we can't target
-   * emulated nullptr the same way, because passing __null to an int/long
-   * parameter triggers compiler warnings.  So just give up on this, and provide
-   * this behavior through the default constructor.
-   *
-   * We can revert to simply explicit (T*) and implicit (decltype(nullptr)) when
-   * nullptr no longer needs to be emulated to support the ancient b2g compiler.
-   * (The () overload could also be removed, if desired, if we changed callers.)
-   */
-  already_AddRefed() : mRawPtr(nullptr) {}
-
-  // The return and argument types here are arbitrarily selected so no
-  // corresponding member function exists.
-  typedef void (already_AddRefed::* MatchNullptr)(double, float);
-  MOZ_IMPLICIT already_AddRefed(MatchNullptr aRawPtr) : mRawPtr(nullptr) {}
-
-  explicit already_AddRefed(T* aRawPtr) : mRawPtr(aRawPtr) {}
-
-  // Disallowed. Use move semantics instead.
-  already_AddRefed(const already_AddRefed<T>& aOther) MOZ_DELETE;
-
-  already_AddRefed(already_AddRefed<T>&& aOther) : mRawPtr(aOther.take()) {}
-
-  ~already_AddRefed() { MOZ_ASSERT(!mRawPtr); }
-
-  // Specialize the unused operator<< for already_AddRefed, to allow
-  // nsCOMPtr<nsIFoo> foo;
-  // unused << foo.forget();
-  friend void operator<<(const mozilla::unused_t& aUnused,
-                         const already_AddRefed<T>& aRhs)
-  {
-    auto mutableAlreadyAddRefed = const_cast<already_AddRefed<T>*>(&aRhs);
-    aUnused << mutableAlreadyAddRefed->take();
-  }
-
-  MOZ_WARN_UNUSED_RESULT T* take()
-  {
-    T* rawPtr = mRawPtr;
-    mRawPtr = nullptr;
-    return rawPtr;
-  }
-
-  /**
-   * This helper is useful in cases like
-   *
-   *  already_AddRefed<BaseClass>
-   *  Foo()
-   *  {
-   *    nsRefPtr<SubClass> x = ...;
-   *    return x.forget();
-   *  }
-   *
-   * The autoconversion allows one to omit the idiom
-   *
-   *    nsRefPtr<BaseClass> y = x.forget();
-   *    return y.forget();
-   */
-  template<class U>
-  operator already_AddRefed<U>()
-  {
-    U* tmp = mRawPtr;
-    mRawPtr = nullptr;
-    return already_AddRefed<U>(tmp);
-  }
-
-  /**
-   * This helper provides a static_cast replacement for already_AddRefed, so
-   * if you have
-   *
-   *   already_AddRefed<Parent> F();
-   *
-   * you can write
-   *
-   *   already_AddRefed<Child>
-   *   G()
-   *   {
-   *     return F().downcast<Child>();
-   *   }
-   *
-   * instead of
-   *
-   *     return dont_AddRef(static_cast<Child*>(F().get()));
-   */
-  template<class U>
-  already_AddRefed<U> downcast()
-  {
-    U* tmp = static_cast<U*>(mRawPtr);
-    mRawPtr = nullptr;
-    return already_AddRefed<U>(tmp);
-  }
-
-private:
-  T* MOZ_OWNING_REF mRawPtr;
-};
-
-#endif // AlreadyAddRefed_h
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -34,17 +34,16 @@ XPIDL_SOURCES += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     XPIDL_SOURCES += [
         'nsIMacUtils.idl',
     ]
 
 XPIDL_MODULE = 'xpcom_base'
 
 EXPORTS += [
-    'AlreadyAddRefed.h',
     'CodeAddressService.h',
     'ErrorList.h',
     'nsAgg.h',
     'nsAutoPtr.h',
     'nsAutoRef.h',
     'nsCom.h',
     'nscore.h',
     'nsCycleCollector.h',
--- a/xpcom/base/nsRefPtr.h
+++ b/xpcom/base/nsRefPtr.h
@@ -2,18 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsRefPtr_h
 #define nsRefPtr_h
 
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Attributes.h"
-#include "AlreadyAddRefed.h"
 #include "nsDebug.h"
 #include "nsISupportsUtils.h"
 
 /*****************************************************************************/
 
 // template <class T> class nsRefPtrGetterAddRefs;
 
 class nsCOMPtr_helper;
--- a/xpcom/glue/nsCOMPtr.h
+++ b/xpcom/glue/nsCOMPtr.h
@@ -15,23 +15,23 @@
  *
  *
  * nsCOMPtr
  *   better than a raw pointer
  * for owning objects
  *                      -- scc
  */
 
+#include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Move.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/TypeTraits.h"
 
-#include "AlreadyAddRefed.h"
 #include "nsDebug.h" // for |NS_ABORT_IF_FALSE|, |NS_ASSERTION|
 #include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
 
 #include "nsCycleCollectionNoteChild.h"
 
 
 /*
  * WARNING: This file defines several macros for internal use only. These