Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
chunk.h
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <optional>
17#include <utility>
18
19#include "pw_assert/assert.h"
20#include "pw_bytes/span.h"
21#include "pw_multibuf/config.h"
22#include "pw_sync/mutex.h"
23
24namespace pw::multibuf {
25
26class ChunkRegionTracker;
27class OwnedChunk;
28
48class PW_MULTIBUF_DEPRECATED Chunk {
49 public:
50 Chunk() = delete;
51 // Not copyable or movable.
52 Chunk(Chunk&) = delete;
53 Chunk& operator=(Chunk&) = delete;
54 Chunk(Chunk&&) = delete;
55 Chunk& operator=(Chunk&&) = delete;
56
57 std::byte* data() { return span_.data(); }
58 const std::byte* data() const { return span_.data(); }
59 size_t size() const { return span_.size(); }
60 [[nodiscard]] bool empty() const { return span_.empty(); }
61
62 std::byte& operator[](size_t index) { return span_[index]; }
63 const std::byte& operator[](size_t index) const { return span_[index]; }
64
65 // Container declarations
66 using element_type = std::byte;
67 using value_type = std::byte;
68 using size_type = size_t;
69 using difference_type = ptrdiff_t;
70 using pointer = std::byte*;
71 using const_pointer = const std::byte*;
72 using reference = std::byte&;
73 using const_reference = const std::byte&;
74 using iterator = std::byte*;
75 using const_iterator = const std::byte*;
76 using reverse_iterator = std::byte*;
77 using const_reverse_iterator = const std::byte*;
78
79 std::byte* begin() { return span_.data(); }
80 const std::byte* begin() const { return cbegin(); }
81 const std::byte* cbegin() const { return span_.data(); }
82 std::byte* end() { return span_.data() + span_.size(); }
83 const std::byte* end() const { return cend(); }
84 const std::byte* cend() const { return span_.data() + span_.size(); }
85
90 [[nodiscard]] bool CanMerge(const Chunk& next_chunk) const;
91
102 bool Merge(OwnedChunk& next_chunk);
103
113 [[nodiscard]] bool ClaimPrefix(size_t bytes_to_claim);
114
123 [[nodiscard]] bool ClaimSuffix(size_t bytes_to_claim);
124
133 void DiscardPrefix(size_t bytes_to_discard);
134
143 void Slice(size_t begin, size_t end);
144
152 void Truncate(size_t len);
153
162 std::optional<OwnedChunk> TakePrefix(size_t bytes_to_take);
163
172 std::optional<OwnedChunk> TakeSuffix(size_t bytes_to_take);
173
174 private:
175 Chunk(ChunkRegionTracker* region_tracker, ByteSpan span)
176 : region_tracker_(region_tracker),
177 next_in_region_(nullptr),
178 prev_in_region_(nullptr),
179 next_in_buf_(nullptr),
180 span_(span) {}
181
182 // NOTE: these functions are logically
183 // `PW_EXCLUSIVE_LOCKS_REQUIRED(region_tracker_->lock_)`, however this
184 // annotation cannot be applied due to the forward declaration of
185 // `region_tracker_`.
186 void InsertAfterInRegionList(Chunk* new_chunk);
187 void InsertBeforeInRegionList(Chunk* new_chunk);
188 void RemoveFromRegionList();
189
199 void Free();
200
202 ChunkRegionTracker* const region_tracker_;
203
211 Chunk* next_in_region_;
212
220 Chunk* prev_in_region_;
221
228 Chunk* next_in_buf_;
229
242 ByteSpan span_;
243
244 friend class ChunkRegionTracker; // For the constructor
245 friend class OwnedChunk; // for `Free`.
246 friend class MultiBuf; // for `next_in_buf_`.
247 friend class MultiBufChunks; // for `Free` and `next_in_buf_`.
248};
249
272class PW_MULTIBUF_DEPRECATED ChunkRegionTracker {
273 public:
280 std::optional<OwnedChunk> CreateFirstChunk();
281
282 protected:
283 ChunkRegionTracker() = default;
284 virtual ~ChunkRegionTracker() = default;
285
290 virtual void Destroy() = 0;
291
300 virtual ByteSpan Region() const = 0;
301
304 virtual void* AllocateChunkClass() = 0;
305
307 virtual void DeallocateChunkClass(void*) = 0;
308
309 private:
316 pw::sync::Mutex lock_;
317 friend Chunk;
318};
319
324class PW_MULTIBUF_DEPRECATED OwnedChunk {
325 public:
326 OwnedChunk() : inner_(nullptr) {}
327 OwnedChunk(OwnedChunk&& other) noexcept : inner_(other.inner_) {
328 other.inner_ = nullptr;
329 }
330 OwnedChunk& operator=(OwnedChunk&& other) noexcept {
331 inner_ = other.inner_;
332 other.inner_ = nullptr;
333 return *this;
334 }
336 ~OwnedChunk() { Release(); }
337
338 std::byte* data() {
339 return const_cast<std::byte*>(std::as_const(*this).data());
340 }
341 const std::byte* data() const {
342 return inner_ == nullptr ? nullptr : inner_->data();
343 }
344
345 size_t size() const { return inner_ == nullptr ? 0 : inner_->size(); }
346
347 std::byte& operator[](size_t index) { return data()[index]; }
348 std::byte operator[](size_t index) const { return data()[index]; }
349
350 // Container declarations
351 using element_type = std::byte;
352 using value_type = std::byte;
353 using size_type = size_t;
354 using difference_type = ptrdiff_t;
355 using pointer = std::byte*;
356 using const_pointer = const std::byte*;
357 using reference = std::byte&;
358 using const_reference = const std::byte&;
359 using iterator = std::byte*;
360 using const_iterator = const std::byte*;
361 using reverse_iterator = std::byte*;
362 using const_reverse_iterator = const std::byte*;
363
364 std::byte* begin() { return data(); }
365 const std::byte* begin() const { return cbegin(); }
366 const std::byte* cbegin() const { return data(); }
367 std::byte* end() { return data() + size(); }
368 const std::byte* end() const { return cend(); }
369 const std::byte* cend() const { return data() + size(); }
370
371 Chunk& operator*() { return *inner_; }
372 const Chunk& operator*() const { return *inner_; }
373 Chunk* operator->() { return inner_; }
374 const Chunk* operator->() const { return inner_; }
375
385 void Release();
386
389 Chunk* Take() && {
390 Chunk* result = inner_;
391 inner_ = nullptr;
392 return result;
393 }
394
395 private:
397 OwnedChunk(Chunk* inner) : inner_(inner) {}
398
400 Chunk* inner_;
401
404 friend class Chunk;
405 friend class ChunkRegionTracker;
406 friend class MultiBuf;
407 friend class MultiBufChunks;
408};
409
410} // namespace pw::multibuf
Definition: chunk.h:48
std::optional< OwnedChunk > TakeSuffix(size_t bytes_to_take)
void DiscardPrefix(size_t bytes_to_discard)
bool Merge(OwnedChunk &next_chunk)
void Truncate(size_t len)
void Slice(size_t begin, size_t end)
bool ClaimSuffix(size_t bytes_to_claim)
bool ClaimPrefix(size_t bytes_to_claim)
std::optional< OwnedChunk > TakePrefix(size_t bytes_to_take)
bool CanMerge(const Chunk &next_chunk) const
Definition: chunk.h:272
virtual void DeallocateChunkClass(void *)=0
Deallocates a pointer returned by AllocateChunkClass.
virtual ByteSpan Region() const =0
std::optional< OwnedChunk > CreateFirstChunk()
virtual void * AllocateChunkClass()=0
A Chunk-oriented view of a MultiBuf.
Definition: multibuf_v1.h:29
Definition: multibuf_v1.h:246
Definition: chunk.h:324
~OwnedChunk()
This method will acquire a mutex and is not IRQ safe.
Definition: chunk.h:336
Chunk * Take() &&
Definition: chunk.h:389
Definition: mutex.h:42