summaryrefslogtreecommitdiff
path: root/layout/style/HandleRefPtr.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/HandleRefPtr.h')
-rw-r--r--layout/style/HandleRefPtr.h133
1 files changed, 133 insertions, 0 deletions
diff --git a/layout/style/HandleRefPtr.h b/layout/style/HandleRefPtr.h
new file mode 100644
index 0000000000..0a73a4cf70
--- /dev/null
+++ b/layout/style/HandleRefPtr.h
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=2 sw=2 et tw=78:
+ * 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/.
+ */
+
+/* smart pointer for strong references to objects through pointer-like
+ * "handle" objects */
+
+#include <algorithm>
+#include "mozilla/Assertions.h"
+
+#ifndef mozilla_HandleRefPtr_h
+#define mozilla_HandleRefPtr_h
+
+namespace mozilla {
+
+/**
+ * A class for holding strong references to handle-managed objects.
+ *
+ * This is intended for use with objects like RestyleManagerHandle,
+ * where the handle type is not a pointer but which can still have
+ * ->AddRef() and ->Release() called on it.
+ */
+template<typename T>
+class HandleRefPtr
+{
+public:
+ HandleRefPtr() {}
+
+ HandleRefPtr(HandleRefPtr<T>& aRhs)
+ {
+ assign(aRhs.mHandle);
+ }
+
+ HandleRefPtr(HandleRefPtr<T>&& aRhs)
+ {
+ std::swap(mHandle, aRhs.mHandle);
+ }
+
+ MOZ_IMPLICIT HandleRefPtr(T aRhs)
+ {
+ assign(aRhs);
+ }
+
+ HandleRefPtr<T>& operator=(HandleRefPtr<T>& aRhs)
+ {
+ assign(aRhs.mHandle);
+ return *this;
+ }
+
+ HandleRefPtr<T>& operator=(T aRhs)
+ {
+ assign(aRhs);
+ return *this;
+ }
+
+ ~HandleRefPtr() { assign(nullptr); }
+
+ explicit operator bool() const { return !!mHandle; }
+ bool operator!() const { return !mHandle; }
+
+ operator T() const { return mHandle; }
+ T operator->() const { return mHandle; }
+
+ void swap(HandleRefPtr<T>& aOther)
+ {
+ std::swap(mHandle, aOther.mHandle);
+ }
+
+private:
+ void assign(T aPtr)
+ {
+ // AddRef early so |aPtr| can't disappear underneath us.
+ if (aPtr) {
+ aPtr->AddRef();
+ }
+
+ // Don't release |mHandle| yet: if |mHandle| indirectly owns |this|,
+ // releasing would invalidate |this|. Swap |aPtr| for |mHandle| so that
+ // |aPtr| lives as long as |this|, then release the new |aPtr| (really the
+ // original |mHandle|) so that if |this| is invalidated, we're not using it
+ // any more.
+ std::swap(mHandle, aPtr);
+
+ if (aPtr) {
+ aPtr->Release();
+ }
+ }
+
+ T mHandle;
+};
+
+template<typename T>
+inline bool operator==(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
+{
+ return static_cast<T>(aLHS) == static_cast<T>(aRHS);
+}
+
+template<typename T>
+inline bool operator==(const HandleRefPtr<T>& aLHS, T aRHS)
+{
+ return static_cast<T>(aLHS) == aRHS;
+}
+
+template<typename T>
+inline bool operator==(T aLHS, const HandleRefPtr<T>& aRHS)
+{
+ return aLHS == static_cast<T>(aRHS);
+}
+
+template<typename T>
+inline bool operator!=(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
+{
+ return !(aLHS == aRHS);
+}
+
+template<typename T>
+inline bool operator!=(const HandleRefPtr<T>& aLHS, T aRHS)
+{
+ return !(aLHS == aRHS);
+}
+
+template<typename T>
+inline bool operator!=(T aLHS, const HandleRefPtr<T>& aRHS)
+{
+ return !(aLHS == aRHS);
+}
+
+} // namespace mozilla
+
+#endif // mozilla_HandleRefPtr_h