zpp
Zephyr C++20 Framework
mem_slab.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2021 Erwin Rol <erwin@erwinrol.com>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 #ifndef ZPP_INCLUDE_ZPP_MEM_SLAB_HPP
8 #define ZPP_INCLUDE_ZPP_MEM_SLAB_HPP
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #include <cstdint>
14 #include <chrono>
15 #include <array>
16 
17 #include <zpp/utils.hpp>
18 
19 namespace zpp {
20 
26 template<class T_MemSlab>
28 public:
29  using native_type = struct k_mem_slab;
32 protected:
33  constexpr mem_slab_base() noexcept {}
34 public:
40  [[nodiscard]] void*
41  allocate() noexcept
42  {
43  void* vp{nullptr};
44 
45  auto rc = k_mem_slab_alloc(native_handle(), &vp, K_FOREVER);
46 
47  if (rc == 0) {
48  return vp;
49  } else {
50  return nullptr;
51  }
52  }
53 
59  [[nodiscard]] void*
60  try_allocate() noexcept
61  {
62  void* vp{nullptr};
63 
64  auto rc = k_mem_slab_alloc(native_handle(), &vp, K_NO_WAIT);
65 
66  if (rc == 0) {
67  return vp;
68  } else {
69  return nullptr;
70  }
71  }
72 
80  template<class T_Rep, class T_Period>
81  [[nodiscard]] void*
82  try_allocate_for(const std::chrono::duration<T_Rep, T_Period>& timeout) noexcept
83  {
84  using namespace std::chrono;
85 
86  void* vp{nullptr};
87 
88  auto rc = k_mem_slab_alloc(native_handle(), &vp, to_timeout(timeout));
89 
90  if (rc == 0) {
91  return vp;
92  } else {
93  return nullptr;
94  }
95  }
96 
102  void deallocate(void* vp) noexcept
103  {
104  if (vp != nullptr) {
105  k_mem_slab_free(native_handle(), &vp);
106  }
107  }
108 
114  constexpr auto block_size() const noexcept
115  {
116  return native_handle()->block_size;
117  }
118 
124  constexpr auto total_block_count() const noexcept
125  {
126  return native_handle()->num_blocks;
127  }
128 
134  constexpr auto used_block_count() noexcept
135  {
136  return k_mem_slab_num_used_get(native_handle());
137  }
138 
144  constexpr auto free_block_count() noexcept
145  {
146  return k_mem_slab_num_free_get(native_handle());
147  }
148 
149 
155  auto native_handle() noexcept -> native_pointer
156  {
157  return static_cast<T_MemSlab*>(this)->native_handle();
158  }
159 
165  auto native_handle() const noexcept -> native_const_pointer
166  {
167  return static_cast<const T_MemSlab*>(this)->native_handle();
168  }
169 public:
170  mem_slab_base(const mem_slab_base&) = delete;
174 };
175 
176 
180 template<uint32_t T_BlockSize, uint32_t T_BlockCount, uint32_t T_Align=sizeof(void*)>
181 class mem_slab : public mem_slab_base<mem_slab<T_BlockSize, T_BlockCount, T_Align>>
182 {
183  static_assert(T_BlockCount > 0);
184  static_assert(is_multiple_of(T_BlockSize, 4) == true);
185  static_assert(T_Align >= sizeof(void*));
186  static_assert(is_power_of_two(T_Align));
187  static_assert(T_BlockSize >= T_Align);
188  static_assert((T_BlockSize % T_Align) == 0);
189 public:
193 public:
197  mem_slab() noexcept
198  {
199  k_mem_slab_init(&m_mem_slab, m_mem_buffer.data(), T_BlockSize, T_BlockCount);
200  }
201 
207  constexpr auto native_handle() noexcept -> native_pointer
208  {
209  return &m_mem_slab;
210  }
211 
217  constexpr auto native_handle() const noexcept -> native_const_pointer
218  {
219  return &m_mem_slab;
220  }
221 private:
222  native_type m_mem_slab{};
223  alignas(T_Align) std::array<uint8_t, T_BlockSize * T_BlockCount> m_mem_buffer;
224 public:
225  mem_slab(const mem_slab&) = delete;
226  mem_slab(mem_slab&&) = delete;
227  mem_slab& operator=(const mem_slab&) = delete;
229 };
230 
234 class mem_slab_ref : public mem_slab_base<mem_slab_ref> {
235 public:
242  explicit constexpr mem_slab_ref(native_pointer m) noexcept
243  : m_mem_slab_ptr(m)
244  {
245  __ASSERT_NO_MSG(m_mem_slab_ptr != nullptr);
246  }
247 
254  template<class T_MemSlab>
255  explicit constexpr mem_slab_ref(T_MemSlab& m) noexcept
256  : m_mem_slab_ptr(m.native_handle())
257  {
258  __ASSERT_NO_MSG(m_mem_slab_ptr != nullptr);
259  }
260 
269  constexpr mem_slab_ref& operator=(native_pointer m) noexcept
270  {
271  m_mem_slab_ptr = m;
272  __ASSERT_NO_MSG(m_mem_slab_ptr != nullptr);
273  return *this;
274  }
275 
284  template<class T_MemSlab>
285  constexpr mem_slab_ref& operator=(T_MemSlab& m) noexcept
286  {
287  m_mem_slab_ptr = m.native_handle();
288  __ASSERT_NO_MSG(m_mem_slab_ptr != nullptr);
289  return *this;
290  }
291 
297  constexpr auto native_handle() noexcept -> native_pointer
298  {
299  return m_mem_slab_ptr;
300  }
301 
307  constexpr auto native_handle() const noexcept -> native_const_pointer
308  {
309  return m_mem_slab_ptr;
310  }
311 private:
312  native_pointer m_mem_slab_ptr{ nullptr };
313 public:
314  mem_slab_ref() = delete;
315 };
316 
317 } // namespace zpp
318 
319 #endif // ZPP_INCLUDE_ZPP_MEM_SLAB_HPP
Allocator that uses k_mem_slab for memory.
Definition: mem_slab.hpp:27
constexpr auto free_block_count() noexcept
get current number of free blocks
Definition: mem_slab.hpp:144
native_type const * native_const_pointer
Definition: mem_slab.hpp:31
mem_slab_base & operator=(mem_slab_base &&)=delete
auto native_handle() const noexcept -> native_const_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:165
constexpr auto total_block_count() const noexcept
get maximm number of blocks that can be allocated
Definition: mem_slab.hpp:124
mem_slab_base(const mem_slab_base &)=delete
void * try_allocate_for(const std::chrono::duration< T_Rep, T_Period > &timeout) noexcept
try allocate a memory block waiting with a timeout
Definition: mem_slab.hpp:82
constexpr auto block_size() const noexcept
the size of the memory blocks
Definition: mem_slab.hpp:114
constexpr auto used_block_count() noexcept
get current number of used blocks
Definition: mem_slab.hpp:134
struct k_mem_slab native_type
Definition: mem_slab.hpp:29
mem_slab_base(mem_slab_base &&)=delete
mem_slab_base & operator=(const mem_slab_base &)=delete
native_type * native_pointer
Definition: mem_slab.hpp:30
void * try_allocate() noexcept
try allocate a memory block, not waiting
Definition: mem_slab.hpp:60
void * allocate() noexcept
allocate a memory block, waiting forever
Definition: mem_slab.hpp:41
void deallocate(void *vp) noexcept
deallocate memory
Definition: mem_slab.hpp:102
constexpr mem_slab_base() noexcept
Definition: mem_slab.hpp:33
auto native_handle() noexcept -> native_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:155
A mem_slab class referencing another mem slab object.
Definition: mem_slab.hpp:234
constexpr mem_slab_ref & operator=(native_pointer m) noexcept
Assign a new native k_mem_slab* object.
Definition: mem_slab.hpp:269
mem_slab_ref()=delete
constexpr mem_slab_ref(T_MemSlab &m) noexcept
Construct a reference to another mem_slab object.
Definition: mem_slab.hpp:255
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:307
constexpr mem_slab_ref & operator=(T_MemSlab &m) noexcept
Assign a new native mem slab object.
Definition: mem_slab.hpp:285
constexpr mem_slab_ref(native_pointer m) noexcept
Construct a reference to a native k_mem_slab*.
Definition: mem_slab.hpp:242
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:297
A memory slab class.
Definition: mem_slab.hpp:182
constexpr auto native_handle() noexcept -> native_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:207
mem_slab & operator=(mem_slab &&)=delete
mem_slab & operator=(const mem_slab &)=delete
mem_slab(const mem_slab &)=delete
mem_slab() noexcept
Default constructor.
Definition: mem_slab.hpp:197
constexpr auto native_handle() const noexcept -> native_const_pointer
get the native zephyr mem slab handle.
Definition: mem_slab.hpp:217
mem_slab(mem_slab &&)=delete
constexpr k_timeout_t to_timeout(const std::chrono::duration< T_Rep, T_Period > &d) noexcept
convert a duration to tick
Definition: clock.hpp:88
consteval bool is_power_of_two(uint32_t value) noexcept
check if a value is a power of two
Definition: utils.hpp:97
consteval bool is_multiple_of(uint32_t value, uint32_t base)
Check if a value is a multiple of another value.
Definition: utils.hpp:117