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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ipc_BigBuffer_h
8 #define mozilla_ipc_BigBuffer_h
12 #include "mozilla/Span.h"
13 #include "mozilla/Variant.h"
14 #include "mozilla/ipc/SharedMemory.h"
16 namespace mozilla::ipc
{
20 static constexpr size_t kShmemThreshold
= 64 * 1024;
22 static BigBuffer
TryAlloc(const size_t aSize
) {
23 auto ret
= BigBuffer
{};
24 auto data
= TryAllocBuffer(aSize
);
27 ret
.mData
= std::move(data
.ref());
32 // Return a new BigBuffer which wraps no data.
33 BigBuffer() : mSize(0), mData(NoData()) {}
35 BigBuffer(const BigBuffer
&) = delete;
36 BigBuffer
& operator=(const BigBuffer
&) = delete;
38 BigBuffer(BigBuffer
&& aOther
) noexcept
39 : mSize(std::exchange(aOther
.mSize
, 0)),
40 mData(std::exchange(aOther
.mData
, NoData())) {}
42 BigBuffer
& operator=(BigBuffer
&& aOther
) noexcept
{
43 mSize
= std::exchange(aOther
.mSize
, 0);
44 mData
= std::exchange(aOther
.mData
, NoData());
48 // Create a new BigBuffer with the given size.
49 // The buffer will be created uninitialized and must be fully initialized
50 // before sending over IPC to avoid leaking uninitialized memory to another
52 explicit BigBuffer(size_t aSize
) : mSize(aSize
), mData(AllocBuffer(aSize
)) {}
54 // Create a new BigBuffer containing the data from the provided byte slice.
55 explicit BigBuffer(Span
<const uint8_t> aData
) : BigBuffer(aData
.Length()) {
56 memcpy(Data(), aData
.Elements(), aData
.Length());
59 // Marker to indicate that a particular constructor of BigBuffer adopts
60 // ownership of the provided data.
63 // Create a new BigBuffer from an existing shared memory region, taking
64 // ownership of that shared memory region. The shared memory region must be
65 // non-null, mapped, and large enough to fit aSize bytes.
66 BigBuffer(Adopt
, SharedMemory
* aSharedMemory
, size_t aSize
);
68 // Create a new BigBuffer from an existing memory buffer, taking ownership of
69 // that memory region. The region will be freed using `free()` when it is no
71 BigBuffer(Adopt
, uint8_t* aData
, size_t aSize
);
73 ~BigBuffer() = default;
75 // Returns a pointer to the data stored by this BigBuffer, regardless of
76 // backing storage type.
78 const uint8_t* Data() const;
80 // Returns the size of the data stored by this BigBuffer, regardless of
81 // backing storage type.
82 size_t Size() const { return mSize
; }
84 // Get a view of the BigBuffer's data as a span.
85 Span
<uint8_t> AsSpan() { return Span
{Data(), Size()}; }
86 Span
<const uint8_t> AsSpan() const { return Span
{Data(), Size()}; }
88 // If the BigBuffer is backed by shared memory, returns a pointer to the
89 // backing SharedMemory region.
90 SharedMemory
* GetSharedMemory() const {
91 return mData
.is
<1>() ? mData
.as
<1>().get() : nullptr;
95 friend struct IPC::ParamTraits
<mozilla::ipc::BigBuffer
>;
97 using Storage
= Variant
<UniqueFreePtr
<uint8_t[]>, RefPtr
<SharedMemory
>>;
99 // Empty storage which holds no data.
100 static Storage
NoData() { return AsVariant(UniqueFreePtr
<uint8_t[]>{}); }
102 // Fallibly allocate a new storage of the given size.
103 static Maybe
<Storage
> TryAllocBuffer(size_t aSize
);
105 // Infallibly allocate a new storage of the given size.
106 static Storage
AllocBuffer(size_t aSize
) {
107 auto ret
= TryAllocBuffer(aSize
);
111 return std::move(ret
.ref());
118 } // namespace mozilla::ipc
123 struct ParamTraits
<mozilla::ipc::BigBuffer
> {
124 using paramType
= mozilla::ipc::BigBuffer
;
125 static void Write(MessageWriter
* aWriter
, paramType
&& aParam
);
126 static bool Read(MessageReader
* aReader
, paramType
* aResult
);
131 #endif // mozilla_BigBuffer_h