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;
49 void operator()(const void* ptr
) { free(const_cast<void*>(ptr
)); }
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
;
59 # error "Unsupported OS?"
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 {
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) {
79 return mHandle
!= kInvalidHandle
;
82 operator FileHandleType() const { return mHandle
; }
85 // NSPR uses an integer type for PROsfd, so this conversion is
86 // provided for working with it without needing reinterpret casts
88 operator std::intptr_t() const {
89 return reinterpret_cast<std::intptr_t>(mHandle
);
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
;
101 FileHandleType mHandle
;
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;
108 static constexpr FileHandleType kInvalidHandle
= -1;
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
{
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
; }
146 typename
Ptr::Pointer mRawPtr
= nullptr;
149 return UniquePtrGetterTransfers(up
);
152 } // namespace mozilla
154 #endif // mozilla_UniquePtrExtensions_h