Bug 1627646 - Avoid creating a Port object when there are no listeners r=mixedpuppy
[gecko.git] / mfbt / UniquePtrExtensions.h
blob97cad82eba59aeb6ccd085d7617009b6ffec227d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Useful extensions to UniquePtr. */
9 #ifndef mozilla_UniquePtrExtensions_h
10 #define mozilla_UniquePtrExtensions_h
12 #include <type_traits>
14 #include "mozilla/Attributes.h"
15 #include "mozilla/fallible.h"
16 #include "mozilla/UniquePtr.h"
18 #ifdef XP_WIN
19 # include <cstdint>
20 #endif
22 namespace mozilla {
24 /**
25 * MakeUniqueFallible works exactly like MakeUnique, except that the memory
26 * allocation performed is done fallibly, i.e. it can return nullptr.
28 template <typename T, typename... Args>
29 typename detail::UniqueSelector<T>::SingleObject MakeUniqueFallible(
30 Args&&... aArgs) {
31 return UniquePtr<T>(new (fallible) T(std::forward<Args>(aArgs)...));
34 template <typename T>
35 typename detail::UniqueSelector<T>::UnknownBound MakeUniqueFallible(
36 decltype(sizeof(int)) aN) {
37 using ArrayType = std::remove_extent_t<T>;
38 return UniquePtr<T>(new (fallible) ArrayType[aN]());
41 template <typename T, typename... Args>
42 typename detail::UniqueSelector<T>::KnownBound MakeUniqueFallible(
43 Args&&... aArgs) = delete;
45 namespace detail {
47 template <typename T>
48 struct FreePolicy {
49 void operator()(const void* ptr) { free(const_cast<void*>(ptr)); }
52 #if defined(XP_WIN)
53 // Can't include <windows.h> to get the actual definition of HANDLE
54 // because of namespace pollution.
55 typedef void* FileHandleType;
56 #elif defined(XP_UNIX)
57 typedef int FileHandleType;
58 #else
59 # error "Unsupported OS?"
60 #endif
62 struct FileHandleHelper {
63 MOZ_IMPLICIT FileHandleHelper(FileHandleType aHandle) : mHandle(aHandle) {}
65 MOZ_IMPLICIT constexpr FileHandleHelper(std::nullptr_t)
66 : mHandle(kInvalidHandle) {}
68 bool operator!=(std::nullptr_t) const {
69 #ifdef XP_WIN
70 // Windows uses both nullptr and INVALID_HANDLE_VALUE (-1 cast to
71 // HANDLE) in different situations, but nullptr is more reliably
72 // null while -1 is also valid input to some calls that take
73 // handles. So class considers both to be null (since neither
74 // should be closed) but default-constructs as nullptr.
75 if (mHandle == (void*)-1) {
76 return false;
78 #endif
79 return mHandle != kInvalidHandle;
82 operator FileHandleType() const { return mHandle; }
84 #ifdef XP_WIN
85 // NSPR uses an integer type for PROsfd, so this conversion is
86 // provided for working with it without needing reinterpret casts
87 // everywhere.
88 operator std::intptr_t() const {
89 return reinterpret_cast<std::intptr_t>(mHandle);
91 #endif
93 // When there's only one user-defined conversion operator, the
94 // compiler will use that to derive equality, but that doesn't work
95 // when the conversion is ambiguoug (the XP_WIN case above).
96 bool operator==(const FileHandleHelper& aOther) const {
97 return mHandle == aOther.mHandle;
100 private:
101 FileHandleType mHandle;
103 #ifdef XP_WIN
104 // See above for why this is nullptr. (Also, INVALID_HANDLE_VALUE
105 // can't be expressed as a constexpr.)
106 static constexpr FileHandleType kInvalidHandle = nullptr;
107 #else
108 static constexpr FileHandleType kInvalidHandle = -1;
109 #endif
112 struct FileHandleDeleter {
113 typedef FileHandleHelper pointer;
114 MFBT_API void operator()(FileHandleHelper aHelper);
117 } // namespace detail
119 template <typename T>
120 using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
122 // A RAII class for the OS construct used for open files and similar
123 // objects: a file descriptor on Unix or a handle on Windows.
124 using UniqueFileHandle =
125 UniquePtr<detail::FileHandleType, detail::FileHandleDeleter>;
127 // Helper for passing a UniquePtr to an old-style function that uses raw
128 // pointers for out params. Example usage:
130 // void AllocateFoo(Foo** out) { *out = new Foo(); }
131 // UniquePtr<Foo> foo;
132 // AllocateFoo(getter_Transfers(foo));
133 template <typename T, typename D>
134 auto getter_Transfers(UniquePtr<T, D>& up) {
135 class MOZ_TEMPORARY_CLASS UniquePtrGetterTransfers {
136 public:
137 using Ptr = UniquePtr<T, D>;
138 explicit UniquePtrGetterTransfers(Ptr& p) : mPtr(p) {}
139 ~UniquePtrGetterTransfers() { mPtr.reset(mRawPtr); }
141 operator typename Ptr::ElementType**() { return &mRawPtr; }
142 typename Ptr::ElementType*& operator*() { return mRawPtr; }
144 private:
145 Ptr& mPtr;
146 typename Ptr::Pointer mRawPtr = nullptr;
149 return UniquePtrGetterTransfers(up);
152 } // namespace mozilla
154 #endif // mozilla_UniquePtrExtensions_h