Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / ipc / glue / BigBuffer.h
blob7136b6c03c0dc28ca35ea2aa98521e5fa7c6ed45
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
10 #include <stdlib.h>
11 #include <inttypes.h>
12 #include "mozilla/Span.h"
13 #include "mozilla/Variant.h"
14 #include "mozilla/ipc/SharedMemory.h"
16 namespace mozilla::ipc {
18 class BigBuffer {
19 public:
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);
25 if (data) {
26 ret.mSize = aSize;
27 ret.mData = std::move(data.ref());
29 return ret;
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());
45 return *this;
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
51 // process.
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.
61 struct Adopt {};
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
70 // longer needed.
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.
77 uint8_t* Data();
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;
94 private:
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);
108 if (!ret) {
109 NS_ABORT_OOM(aSize);
111 return std::move(ret.ref());
114 size_t mSize;
115 Storage mData;
118 } // namespace mozilla::ipc
120 namespace IPC {
122 template <>
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);
129 } // namespace IPC
131 #endif // mozilla_BigBuffer_h