[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-debug / mozilla / ProfileBufferChunkManagerSingle.h
blobc91b38cbdbee32f3623eb60e58f163bd57b57c59
1 /* -*- Mode: C++; tab-width: 2; 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 #ifndef ProfileBufferChunkManagerSingle_h
8 #define ProfileBufferChunkManagerSingle_h
10 #include "mozilla/ProfileBufferChunkManager.h"
12 #ifdef DEBUG
13 # include "mozilla/Atomics.h"
14 #endif // DEBUG
16 namespace mozilla {
18 // Manages only one Chunk.
19 // The first call to `Get`/`RequestChunk()` will retrieve the one chunk, and all
20 // subsequent calls will return nullptr. That chunk may still be released, but
21 // it will never be destroyed or recycled.
22 // Unlike others, this manager may be `Reset()`, to allow another round of
23 // small-data gathering.
24 // The main use is with short-lived ProfileChunkedBuffers that collect little
25 // data that can fit in one chunk, e.g., capturing one stack.
26 // It is not thread-safe.
27 class ProfileBufferChunkManagerSingle final : public ProfileBufferChunkManager {
28 public:
29 using Length = ProfileBufferChunk::Length;
31 // Use a preallocated chunk. (Accepting null to gracefully handle OOM.)
32 explicit ProfileBufferChunkManagerSingle(UniquePtr<ProfileBufferChunk> aChunk)
33 : mInitialChunk(std::move(aChunk)),
34 mBufferBytes(mInitialChunk ? mInitialChunk->BufferBytes() : 0) {
35 MOZ_ASSERT(!mInitialChunk || !mInitialChunk->GetNext(),
36 "Expected at most one chunk");
39 // ChunkMinBufferBytes: Minimum number of user-available bytes in the Chunk.
40 // Note that Chunks use a bit more memory for their header.
41 explicit ProfileBufferChunkManagerSingle(Length aChunkMinBufferBytes)
42 : mInitialChunk(ProfileBufferChunk::Create(aChunkMinBufferBytes)),
43 mBufferBytes(mInitialChunk ? mInitialChunk->BufferBytes() : 0) {}
45 #ifdef DEBUG
46 ~ProfileBufferChunkManagerSingle() { MOZ_ASSERT(mVirtuallyLocked == false); }
47 #endif // DEBUG
49 // Reset this manager, using the provided chunk (probably coming from the
50 // ProfileChunkedBuffer that just used it); if null, fallback on current or
51 // released chunk.
52 void Reset(UniquePtr<ProfileBufferChunk> aPossibleChunk) {
53 if (aPossibleChunk) {
54 mInitialChunk = std::move(aPossibleChunk);
55 mReleasedChunk = nullptr;
56 } else if (!mInitialChunk) {
57 MOZ_ASSERT(!!mReleasedChunk, "Can't reset properly!");
58 mInitialChunk = std::move(mReleasedChunk);
61 if (mInitialChunk) {
62 mInitialChunk->MarkRecycled();
63 mBufferBytes = mInitialChunk->BufferBytes();
64 } else {
65 mBufferBytes = 0;
69 [[nodiscard]] size_t MaxTotalSize() const final { return mBufferBytes; }
71 // One of `GetChunk` and `RequestChunk` will only work the very first time (if
72 // there's even a chunk).
73 [[nodiscard]] UniquePtr<ProfileBufferChunk> GetChunk() final {
74 MOZ_ASSERT(mUser, "Not registered yet");
75 return std::move(mInitialChunk);
78 void RequestChunk(std::function<void(UniquePtr<ProfileBufferChunk>)>&&
79 aChunkReceiver) final {
80 MOZ_ASSERT(mUser, "Not registered yet");
81 // Simple retrieval.
82 std::move(aChunkReceiver)(GetChunk());
85 void FulfillChunkRequests() final {
86 // Nothing to do here.
89 void ReleaseChunk(UniquePtr<ProfileBufferChunk> aChunk) final {
90 MOZ_ASSERT(mUser, "Not registered yet");
91 if (!aChunk) {
92 return;
94 MOZ_ASSERT(!mReleasedChunk, "Unexpected 2nd released chunk");
95 MOZ_ASSERT(!aChunk->GetNext(), "Only expected one released chunk");
96 mReleasedChunk = std::move(aChunk);
99 void SetChunkDestroyedCallback(
100 std::function<void(const ProfileBufferChunk&)>&& aChunkDestroyedCallback)
101 final {
102 MOZ_ASSERT(mUser, "Not registered yet");
103 // The chunk-destroyed callback will never actually be called, but we keep
104 // the callback here in case the caller expects it to live as long as this
105 // manager.
106 mChunkDestroyedCallback = std::move(aChunkDestroyedCallback);
109 [[nodiscard]] UniquePtr<ProfileBufferChunk> GetExtantReleasedChunks() final {
110 MOZ_ASSERT(mUser, "Not registered yet");
111 return std::move(mReleasedChunk);
114 void ForgetUnreleasedChunks() final {
115 MOZ_ASSERT(mUser, "Not registered yet");
118 [[nodiscard]] size_t SizeOfExcludingThis(
119 MallocSizeOf aMallocSizeOf) const final {
120 MOZ_ASSERT(mUser, "Not registered yet");
121 size_t size = 0;
122 if (mInitialChunk) {
123 size += mInitialChunk->SizeOfIncludingThis(aMallocSizeOf);
125 if (mReleasedChunk) {
126 size += mReleasedChunk->SizeOfIncludingThis(aMallocSizeOf);
128 // Note: Missing size of std::function external resources (if any).
129 return size;
132 [[nodiscard]] size_t SizeOfIncludingThis(
133 MallocSizeOf aMallocSizeOf) const final {
134 MOZ_ASSERT(mUser, "Not registered yet");
135 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
138 protected:
139 // This manager is not thread-safe, so there's not actual locking needed.
140 const ProfileBufferChunk* PeekExtantReleasedChunksAndLock() final {
141 MOZ_ASSERT(mVirtuallyLocked.compareExchange(false, true));
142 MOZ_ASSERT(mUser, "Not registered yet");
143 return mReleasedChunk.get();
145 void UnlockAfterPeekExtantReleasedChunks() final {
146 MOZ_ASSERT(mVirtuallyLocked.compareExchange(true, false));
149 private:
150 // Initial chunk created with this manager, given away at first Get/Request.
151 UniquePtr<ProfileBufferChunk> mInitialChunk;
153 // Storage for the released chunk (which should probably not happen, as it
154 // means the chunk is full).
155 UniquePtr<ProfileBufferChunk> mReleasedChunk;
157 // Size of the one chunk we're managing. Stored here, because the chunk may
158 // be moved out and inaccessible from here.
159 Length mBufferBytes;
161 // The chunk-destroyed callback will never actually be called, but we keep it
162 // here in case the caller expects it to live as long as this manager.
163 std::function<void(const ProfileBufferChunk&)> mChunkDestroyedCallback;
165 #ifdef DEBUG
166 mutable Atomic<bool> mVirtuallyLocked{false};
167 #endif // DEBUG
170 } // namespace mozilla
172 #endif // ProfileBufferChunkManagerSingle_h