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"
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(
31 return UniquePtr
<T
>(new (fallible
) T(std::forward
<Args
>(aArgs
)...));
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;
46 * MakeUniqueForOverwrite and MakeUniqueFallibleForOverwrite are like MakeUnique
47 * and MakeUniqueFallible except they use default-initialization. This is
48 * useful, for example, when you have a POD type array that will be overwritten
49 * directly after construction and so zero-initialization is a waste.
51 template <typename T
, typename
... Args
>
52 typename
detail::UniqueSelector
<T
>::SingleObject
MakeUniqueForOverwrite() {
53 return UniquePtr
<T
>(new T
);
57 typename
detail::UniqueSelector
<T
>::UnknownBound
MakeUniqueForOverwrite(
58 decltype(sizeof(int)) aN
) {
59 using ArrayType
= std::remove_extent_t
<T
>;
60 return UniquePtr
<T
>(new ArrayType
[aN
]);
63 template <typename T
, typename
... Args
>
64 typename
detail::UniqueSelector
<T
>::KnownBound
MakeUniqueForOverwrite(
65 Args
&&... aArgs
) = delete;
67 template <typename T
, typename
... Args
>
68 typename
detail::UniqueSelector
<T
>::SingleObject
69 MakeUniqueForOverwriteFallible() {
70 return UniquePtr
<T
>(new (fallible
) T
);
74 typename
detail::UniqueSelector
<T
>::UnknownBound
MakeUniqueForOverwriteFallible(
75 decltype(sizeof(int)) aN
) {
76 using ArrayType
= std::remove_extent_t
<T
>;
77 return UniquePtr
<T
>(new (fallible
) ArrayType
[aN
]);
80 template <typename T
, typename
... Args
>
81 typename
detail::UniqueSelector
<T
>::KnownBound
MakeUniqueForOverwriteFallible(
82 Args
&&... aArgs
) = delete;
88 void operator()(const void* ptr
) { free(const_cast<void*>(ptr
)); }
92 // Can't include <windows.h> to get the actual definition of HANDLE
93 // because of namespace pollution.
94 typedef void* FileHandleType
;
95 #elif defined(XP_UNIX)
96 typedef int FileHandleType
;
98 # error "Unsupported OS?"
101 struct FileHandleHelper
{
102 MOZ_IMPLICIT
FileHandleHelper(FileHandleType aHandle
) : mHandle(aHandle
) {}
104 MOZ_IMPLICIT
constexpr FileHandleHelper(std::nullptr_t
)
105 : mHandle(kInvalidHandle
) {}
107 bool operator!=(std::nullptr_t
) const {
109 // Windows uses both nullptr and INVALID_HANDLE_VALUE (-1 cast to
110 // HANDLE) in different situations, but nullptr is more reliably
111 // null while -1 is also valid input to some calls that take
112 // handles. So class considers both to be null (since neither
113 // should be closed) but default-constructs as nullptr.
114 if (mHandle
== (void*)-1) {
118 return mHandle
!= kInvalidHandle
;
121 operator FileHandleType() const { return mHandle
; }
124 // NSPR uses an integer type for PROsfd, so this conversion is
125 // provided for working with it without needing reinterpret casts
127 operator std::intptr_t() const {
128 return reinterpret_cast<std::intptr_t>(mHandle
);
132 // When there's only one user-defined conversion operator, the
133 // compiler will use that to derive equality, but that doesn't work
134 // when the conversion is ambiguoug (the XP_WIN case above).
135 bool operator==(const FileHandleHelper
& aOther
) const {
136 return mHandle
== aOther
.mHandle
;
140 FileHandleType mHandle
;
143 // See above for why this is nullptr. (Also, INVALID_HANDLE_VALUE
144 // can't be expressed as a constexpr.)
145 static constexpr FileHandleType kInvalidHandle
= nullptr;
147 static constexpr FileHandleType kInvalidHandle
= -1;
151 struct FileHandleDeleter
{
152 typedef FileHandleHelper pointer
;
153 MFBT_API
void operator()(FileHandleHelper aHelper
);
156 } // namespace detail
158 template <typename T
>
159 using UniqueFreePtr
= UniquePtr
<T
, detail::FreePolicy
<T
>>;
161 // A RAII class for the OS construct used for open files and similar
162 // objects: a file descriptor on Unix or a handle on Windows.
163 using UniqueFileHandle
=
164 UniquePtr
<detail::FileHandleType
, detail::FileHandleDeleter
>;
166 // Helper for passing a UniquePtr to an old-style function that uses raw
167 // pointers for out params. Example usage:
169 // void AllocateFoo(Foo** out) { *out = new Foo(); }
170 // UniquePtr<Foo> foo;
171 // AllocateFoo(getter_Transfers(foo));
172 template <typename T
, typename D
>
173 auto getter_Transfers(UniquePtr
<T
, D
>& up
) {
174 class MOZ_TEMPORARY_CLASS UniquePtrGetterTransfers
{
176 using Ptr
= UniquePtr
<T
, D
>;
177 explicit UniquePtrGetterTransfers(Ptr
& p
) : mPtr(p
) {}
178 ~UniquePtrGetterTransfers() { mPtr
.reset(mRawPtr
); }
180 operator typename
Ptr::ElementType
**() { return &mRawPtr
; }
181 operator void**() { return reinterpret_cast<void**>(&mRawPtr
); }
182 typename
Ptr::ElementType
*& operator*() { return mRawPtr
; }
186 typename
Ptr::Pointer mRawPtr
= nullptr;
189 return UniquePtrGetterTransfers(up
);
192 } // namespace mozilla
194 #endif // mozilla_UniquePtrExtensions_h