xref: /aosp_15_r20/external/pigweed/pw_allocator/public/pw_allocator/buffer.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 <array>
17 #include <cstddef>
18 #include <cstdint>
19 
20 #include "pw_bytes/span.h"
21 #include "pw_result/result.h"
22 
23 namespace pw::allocator {
24 
25 /// Associates a default-constructed type with a memory buffer.
26 ///
27 /// Although the type is arbitrary, the intended purpose of of this class is to
28 /// provide allocators with memory to use, e.g. when testing.
29 ///
30 /// This class uses composition instead of inheritance in order to allow the
31 /// wrapped type's destructor to reference the memory without risk of a
32 /// use-after-free. As a result, the specific methods of the wrapped type
33 /// are not directly accesible. Instead, they can be accessed using the `*` and
34 /// `->` operators, e.g.
35 ///
36 /// @code{.cpp}
37 /// WithBuffer<MyAllocator, 256> allocator;
38 /// allocator->MethodSpecificToMyAllocator();
39 /// @endcode
40 ///
41 /// Note that this class does NOT initialize the allocator, since initialization
42 /// is not specified as part of the `Allocator` interface and may vary from
43 /// allocator to allocator. As a result, typical usage includes deriving a class
44 /// that initializes the wrapped allocator with the buffer in a constructor. See
45 /// `AllocatorForTest` for an example.
46 ///
47 /// @tparam   T             The wrapped object.
48 /// @tparam   kBufferSize   The size of the backing memory, in bytes.
49 /// @tparam   kAlignment    Buffer memory will be aligned to this alignment
50 ///                         boundary.
51 template <typename T, size_t kBufferSize, size_t kAlignment = 1>
52 class WithBuffer {
53  public:
54   static constexpr size_t kCapacity = kBufferSize;
55 
as_bytes()56   ByteSpan as_bytes() { return buffer_; }
data()57   std::byte* data() { return buffer_.data(); }
size()58   size_t size() const { return buffer_.size(); }
59 
60   T& operator*() { return obj_; }
61   const T& operator*() const { return obj_; }
62 
63   T* operator->() { return &obj_; }
64   const T* operator->() const { return &obj_; }
65 
66  private:
67   alignas(kAlignment) std::array<std::byte, kBufferSize> buffer_;
68   T obj_;
69 };
70 
71 }  // namespace pw::allocator
72