C/C++ API Reference
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
27
28class ChunkRegionTracker;
29class OwnedChunk;
30
50class PW_MULTIBUF_DEPRECATED Chunk {
51 public:
52 Chunk() = delete;
53 // Not copyable or movable.
54 Chunk(Chunk&) = delete;
55 Chunk& operator=(Chunk&) = delete;
56 Chunk(Chunk&&) = delete;
57 Chunk& operator=(Chunk&&) = delete;
58
59 std::byte* data() { return span_.data(); }
60 const std::byte* data() const { return span_.data(); }
61 size_t size() const { return span_.size(); }
62 [[nodiscard]] bool empty() const { return span_.empty(); }
63
64 std::byte& operator[](size_t index) { return span_[index]; }
65 const std::byte& operator[](size_t index) const { return span_[index]; }
66
67 // Container declarations
68 using element_type = std::byte;
69 using value_type = std::byte;
70 using size_type = size_t;
71 using difference_type = ptrdiff_t;
72 using pointer = std::byte*;
73 using const_pointer = const std::byte*;
74 using reference = std::byte&;
75 using const_reference = const std::byte&;
76 using iterator = std::byte*;
77 using const_iterator = const std::byte*;
78 using reverse_iterator = std::byte*;
79 using const_reverse_iterator = const std::byte*;
80
81 std::byte* begin() { return span_.data(); }
82 const std::byte* begin() const { return cbegin(); }
83 const std::byte* cbegin() const { return span_.data(); }
84 std::byte* end() { return span_.data() + span_.size(); }
85 const std::byte* end() const { return cend(); }
86 const std::byte* cend() const { return span_.data() + span_.size(); }
87
92 [[nodiscard]] bool CanMerge(const Chunk& next_chunk) const;
93
104 bool Merge(OwnedChunk& next_chunk);
105
115 [[nodiscard]] bool ClaimPrefix(size_t bytes_to_claim);
116
125 [[nodiscard]] bool ClaimSuffix(size_t bytes_to_claim);
126
135 void DiscardPrefix(size_t bytes_to_discard);
136
145 void Slice(size_t begin, size_t end);
146
154 void Truncate(size_t len);
155
164 std::optional<OwnedChunk> TakePrefix(size_t bytes_to_take);
165
174 std::optional<OwnedChunk> TakeSuffix(size_t bytes_to_take);
175
176 private:
177 Chunk(ChunkRegionTracker* region_tracker, ByteSpan span)
178 : region_tracker_(region_tracker),
179 next_in_region_(nullptr),
180 prev_in_region_(nullptr),
181 next_in_buf_(nullptr),
182 span_(span) {}
183
184 // NOTE: these functions are logically
185 // `PW_EXCLUSIVE_LOCKS_REQUIRED(region_tracker_->lock_)`, however this
186 // annotation cannot be applied due to the forward declaration of
187 // `region_tracker_`.
188 void InsertAfterInRegionList(Chunk* new_chunk);
189 void InsertBeforeInRegionList(Chunk* new_chunk);
190 void RemoveFromRegionList();
191
201 void Free();
202
204 ChunkRegionTracker* const region_tracker_;
205
213 Chunk* next_in_region_;
214
222 Chunk* prev_in_region_;
223
230 Chunk* next_in_buf_;
231
244 ByteSpan span_;
245
246 friend class ChunkRegionTracker; // For the constructor
247 friend class OwnedChunk; // for `Free`.
248 friend class MultiBuf; // for `next_in_buf_`.
249 friend class MultiBufChunks; // for `Free` and `next_in_buf_`.
250};
251
274class PW_MULTIBUF_DEPRECATED ChunkRegionTracker {
275 public:
282 std::optional<OwnedChunk> CreateFirstChunk();
283
284 protected:
285 ChunkRegionTracker() = default;
286 virtual ~ChunkRegionTracker() = default;
287
292 virtual void Destroy() = 0;
293
302 virtual ByteSpan Region() const = 0;
303
306 virtual void* AllocateChunkClass() = 0;
307
309 virtual void DeallocateChunkClass(void*) = 0;
310
311 private:
318 pw::sync::Mutex lock_;
319 friend Chunk;
320};
321
326class PW_MULTIBUF_DEPRECATED OwnedChunk {
327 public:
328 OwnedChunk() : inner_(nullptr) {}
329 OwnedChunk(OwnedChunk&& other) noexcept : inner_(other.inner_) {
330 other.inner_ = nullptr;
331 }
332 OwnedChunk& operator=(OwnedChunk&& other) noexcept {
333 inner_ = other.inner_;
334 other.inner_ = nullptr;
335 return *this;
336 }
338 ~OwnedChunk() { Release(); }
339
340 std::byte* data() {
341 return const_cast<std::byte*>(std::as_const(*this).data());
342 }
343 const std::byte* data() const {
344 return inner_ == nullptr ? nullptr : inner_->data();
345 }
346
347 size_t size() const { return inner_ == nullptr ? 0 : inner_->size(); }
348
349 std::byte& operator[](size_t index) { return data()[index]; }
350 std::byte operator[](size_t index) const { return data()[index]; }
351
352 // Container declarations
353 using element_type = std::byte;
354 using value_type = std::byte;
355 using size_type = size_t;
356 using difference_type = ptrdiff_t;
357 using pointer = std::byte*;
358 using const_pointer = const std::byte*;
359 using reference = std::byte&;
360 using const_reference = const std::byte&;
361 using iterator = std::byte*;
362 using const_iterator = const std::byte*;
363 using reverse_iterator = std::byte*;
364 using const_reverse_iterator = const std::byte*;
365
366 std::byte* begin() { return data(); }
367 const std::byte* begin() const { return cbegin(); }
368 const std::byte* cbegin() const { return data(); }
369 std::byte* end() { return data() + size(); }
370 const std::byte* end() const { return cend(); }
371 const std::byte* cend() const { return data() + size(); }
372
373 Chunk& operator*() { return *inner_; }
374 const Chunk& operator*() const { return *inner_; }
375 Chunk* operator->() { return inner_; }
376 const Chunk* operator->() const { return inner_; }
377
387 void Release();
388
391 Chunk* Take() && {
392 Chunk* result = inner_;
393 inner_ = nullptr;
394 return result;
395 }
396
397 private:
399 OwnedChunk(Chunk* inner) : inner_(inner) {}
400
402 Chunk* inner_;
403
406 friend class Chunk;
407 friend class ChunkRegionTracker;
408 friend class MultiBuf;
409 friend class MultiBufChunks;
410};
411
413
414} // namespace pw::multibuf
Definition: chunk.h:50
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:274
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:31
Definition: multibuf_v1.h:248
Definition: chunk.h:326
~OwnedChunk()
This method will acquire a mutex and is not IRQ safe.
Definition: chunk.h:338
Chunk * Take() &&
Definition: chunk.h:391
Definition: mutex.h:40