13#ifndef CMSIS_PLUS_RTOS_OS_MEMORY_H_
14#define CMSIS_PLUS_RTOS_OS_MEMORY_H_
18#if defined(__cplusplus)
35#pragma GCC diagnostic push
37#pragma clang diagnostic ignored "-Wc++98-compat"
38#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
47#pragma GCC diagnostic push
49#pragma clang diagnostic ignored "-Wreserved-identifier"
53#pragma GCC diagnostic pop
64 class critical_section;
74 max (std::size_t a, std::size_t b)
76 return (a >= b) ? a : b;
86 align_size (std::size_t size, std::size_t align)
noexcept
88 return ((size) + (align) - 1L) & ~((align) - 1L);
91 class memory_resource;
153#pragma GCC diagnostic push
154#if defined(__clang__)
155#elif defined(__GNUC__)
156#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
157#pragma GCC diagnostic ignored "-Wsuggest-final-types"
168 static constexpr std::size_t
max_align =
alignof(std::max_align_t);
238 deallocate (
void* addr, std::size_t bytes, std::size_t alignment =
258 reset (
void)
noexcept;
476 std::size_t total_bytes_ = 0;
477 std::size_t allocated_bytes_ = 0;
478 std::size_t free_bytes_ = 0;
479 std::size_t allocated_chunks_ = 0;
480 std::size_t free_chunks_ = 0;
481 std::size_t max_allocated_bytes_ = 0;
482 std::size_t allocations_ = 0;
483 std::size_t deallocations_ = 0;
490#pragma GCC diagnostic pop
680 template<typename T, typename L, F get_resource>
806 select_on_container_copy_construction (
void)
const noexcept;
809 resource (
void)
const noexcept;
822 template<
typename T1,
typename T2,
typename L, F get_resource>
828 get_resource>& rhs)
noexcept;
830 template<
typename T1,
typename T2,
typename L, F get_resource>
836 get_resource>& rhs)
noexcept;
863 using pointer =
typename allocator_traits::pointer;
951 template<
typename T,
typename A,
typename ... Args>
1072 template<
typename T,
typename U = T>
1083 template<
typename T,
typename U = T>
1084 using unique_ptr = std::unique_ptr<T, allocator_deleter<allocator_typed<T, U>>>;
1109 extern memory_resource* default_resource;
1111 extern memory_resource* resource_thread;
1112 extern memory_resource* resource_condition_variable;
1113 extern memory_resource* resource_event_flags;
1114 extern memory_resource* resource_memory_pool;
1115 extern memory_resource* resource_message_queue;
1116 extern memory_resource* resource_mutex;
1117 extern memory_resource* resource_semaphore;
1118 extern memory_resource* resource_timer;
1132 inline memory_resource*
1136 return default_resource;
1151 return resource_thread;
1166 return resource_condition_variable;
1181 return resource_event_flags;
1196 return resource_memory_pool;
1211 return resource_message_queue;
1226 return resource_mutex;
1241 return resource_semaphore;
1256 return resource_timer;
1312 std::size_t alignment)
noexcept
1315 do_deallocate (addr, bytes, alignment);
1332 return do_is_equal (other);
1341 return do_max_size ();
1366 return do_coalesce ();
1379 out_of_memory_handler_ = handler;
1391 return out_of_memory_handler_;
1397 return total_bytes_;
1403 return allocated_bytes_;
1409 return max_allocated_bytes_;
1421 return allocated_chunks_;
1427 return free_chunks_;
1433 return allocations_;
1439 return deallocations_;
1447 "\ttotal: %u bytes, \n"
1448 "\tallocated: %u bytes in %u chunk(s), \n"
1449 "\tfree: %u bytes in %u chunk(s), \n"
1450 "\tmax: %u bytes, \n"
1451 "\tcalls: %u allocs, %u deallocs\n",
1464 return &lhs == &rhs || lhs.is_equal (rhs);
1470 return !(lhs == rhs);
1475 template<
typename T>
1476 template<
typename U>
1479 allocator_stateless_default_resource<U>
const & other __attribute__((unused)))
noexcept
1483 template<
typename T>
1487 scheduler::critical_section scs;
1490 elements *
sizeof(value_type)));
1493 template<
typename T>
1496 value_type* addr, std::size_t elements)
noexcept
1498 scheduler::critical_section scs;
1501 elements *
sizeof(value_type));
1504 template<
typename T>
1513 template<
typename T,
typename U,
typename L, F get_resource>
1516 allocator_stateless_polymorphic_synchronized<T, L, get_resource>
const & lhs,
1517 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & rhs)
noexcept
1519 return *lhs.resource () == *rhs.resource ();
1522 template<
typename T,
typename U,
typename L, F get_resource>
1525 allocator_stateless_polymorphic_synchronized<T, L, get_resource>
const & lhs,
1526 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & rhs)
noexcept
1528 return !(lhs == rhs);
1533 template<
typename T,
typename L, F get_resource>
1537 trace::printf (
"%s() @%p %p\n", __func__,
this, get_resource ());
1540 template<
typename T,
typename L, F get_resource>
1541 template<
typename U>
1544 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & other __attribute__((unused)))
noexcept
1548 template<
typename T,
typename L, F get_resource>
1551 std::size_t elements)
1556 std::size_t ms = max_size ();
1557 if ((ms > 0) && (elements > max_size ()))
1561 "allocator_stateless_polymorphic_synchronized<T>::allocate(size_t n)"
1562 " 'n' exceeds maximum supported size");
1567 std::lock_guard<locker_type> ulk
1570 return static_cast<value_type*
> (get_resource ()->allocate (
1571 elements *
sizeof(value_type),
alignof(value_type)));
1574 template<
typename T,
typename L, F get_resource>
1577 value_type* addr, std::size_t elements)
noexcept
1579 trace::printf (
"%s(%p,%u) @%p\n", __func__, addr, elements,
this);
1582 std::size_t ms = max_size ();
1585 assert (elements <= max_size ());
1590 std::lock_guard<locker_type> ulk
1593 get_resource ()->deallocate (addr, elements *
sizeof(value_type),
1594 alignof(value_type));
1597 template<
typename T,
typename L, F get_resource>
1600 void)
const noexcept
1602 return get_resource ()->max_size () /
sizeof(T);
1606 template<
typename T,
typename L, F get_resource>
1607 inline allocator_stateless_polymorphic_synchronized<T, L, get_resource>
1608 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::select_on_container_copy_construction (
1609 void)
const noexcept
1611 return allocator_stateless_polymorphic_synchronized ();
1614 template<
typename T,
typename L, F get_resource>
1616 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::resource (
1617 void)
const noexcept
1619 return get_resource ();
1625 template<
typename A>
1631 template<
typename A>
1646 template<
typename A>
1648 allocator_deleter<A>::operator() (pointer addr)
const
1652 allocator_type alloc
1656 allocator_traits::destroy (alloc, std::addressof (*addr));
1660 allocator_traits::deallocate (alloc, addr, 1);
1676 template<
typename T,
typename A,
typename ... Args>
1683 using allocator_type = A;
1688 using allocator_traits = std::allocator_traits<A>;
1690 static_assert(std::is_same<typename allocator_traits::value_type, std::remove_cv_t<T>>::value
1691 || std::is_base_of<typename allocator_traits::value_type, std::remove_cv_t<T>>::value,
1692 "Allocator must be of same type or derived.");
1694 static_assert(
sizeof(T) <=
sizeof(
typename allocator_traits::value_type),
1695 "Derived type must not be larger.");
1697 allocator_type alloc
1701 auto p = allocator_traits::allocate (alloc, 1);
1703#if defined(__EXCEPTIONS)
1708 allocator_traits::construct (alloc, std::addressof (*p),
1709 std::forward<Args>(args)...);
1712 using D = allocator_deleter<A>;
1715 return std::unique_ptr<T, D> (p, D (alloc));
1719 allocator_traits::deallocate (alloc, p, 1);
1726 allocator_traits::construct (alloc, std::addressof (*p),
1727 std::forward<Args>(args)...);
1730 using D = allocator_deleter<A>;
1733 return std::unique_ptr<T, D> (p, D (alloc));
1743#pragma GCC diagnostic pop
Base class for named objects.
const char * name(void) const
Get object name.
allocator_deleter()
Default constructor.
A allocator_type
Standard allocator type definition.
allocator_deleter(allocator_deleter &&other)=default
Move constructor.
allocator_deleter(const allocator_type &other)
Copy constructor.
std::allocator_traits< A > allocator_traits
Standard allocator traits definition.
~allocator_deleter()=default
Destruct the allocator deleter.
typename allocator_traits::pointer pointer
Standard allocator based on the RTOS system default memory manager.
void deallocate(value_type *addr, std::size_t elements) noexcept
Deallocate the number of memory blocks of type value_type.
std::size_t max_size(void) const noexcept
The maximum number of elements that can be passed to allocate().
allocator_stateless_default_resource() noexcept=default
Default constructor. Construct a default resource allocator object instance.
value_type * allocate(std::size_t elements)
Allocate a number of memory blocks of type value_type.
T value_type
Type of elements to be allocated.
Allocator using memory resources.
void deallocate(value_type *addr, std::size_t elements) noexcept
Deallocate the number of memory blocks of type value_type.
allocator_stateless_polymorphic_synchronized() noexcept
Default constructor. Construct a default allocator object instance.
std::size_t max_size(void) const noexcept
The maximum number of elements that can be passed to allocate().
value_type * allocate(std::size_t elements)
Allocate a number of memory blocks of type value_type.
Memory resource manager (abstract class).
bool is_equal(memory_resource const &other) const noexcept
Compare for equality with another memory_resource.
virtual bool do_is_equal(memory_resource const &other) const noexcept
Implementation of the equality comparator.
virtual void do_reset(void) noexcept
Implementation of the function to reset the memory manager.
bool coalesce(void) noexcept
Coalesce free blocks.
virtual void * do_allocate(std::size_t bytes, std::size_t alignment)=0
Implementation of the memory allocator.
virtual bool do_coalesce(void) noexcept
Implementation of the function to coalesce free blocks.
std::size_t max_size(void) const noexcept
Get the largest value that can be passed to allocate().
virtual void do_deallocate(void *addr, std::size_t bytes, std::size_t alignment) noexcept=0
Implementation of the memory deallocator.
std::size_t allocated_chunks(void)
Get the current number of allocated chunks.
memory_resource()=default
Default constructor. Construct a memory resource object instance.
void deallocate(void *addr, std::size_t bytes, std::size_t alignment=max_align) noexcept
Deallocate the previously allocated memory block.
std::size_t allocated_bytes(void)
Get the current size of all allocated chunks.
void internal_increase_allocated_statistics(std::size_t bytes) noexcept
Update statistics after allocation.
void * allocate(std::size_t bytes, std::size_t alignment=max_align)
Allocate a memory block.
std::size_t max_allocated_bytes(void)
Get the maximum allocated size.
out_of_memory_handler_t out_of_memory_handler(void)
Get the out of memory handler.
std::size_t allocations(void)
Get the number of allocations.
void reset(void) noexcept
Reset the memory manager to the initial state.
void internal_decrease_allocated_statistics(std::size_t bytes) noexcept
Update statistics after deallocation.
std::size_t total_bytes(void)
Get the total size of managed memory.
virtual std::size_t do_max_size(void) const noexcept
Implementation of the function to get max size.
void trace_print_statistics(void)
Print a long message with usage statistics.
std::size_t deallocations(void)
Get the number of deallocations.
std::size_t free_chunks(void)
Get the current number of free chunks.
virtual ~memory_resource()
Destruct the memory resource object instance.
std::size_t free_bytes(void)
Get the current size of all free chunks.
static constexpr std::size_t max_align
The largest alignment for the platform. Also default when supplied alignment is not supported.
int printf(const char *format,...)
Write a formatted string to the trace device.
memory_resource * get_resource_typed< condition_variable >(void) noexcept
void(*)(void) out_of_memory_handler_t
Type of out of memory handler.
memory_resource * get_resource_typed(void) noexcept
Function template to get a memory resource.
void init_once_default_resource(void)
memory_resource * set_default_resource(memory_resource *res) noexcept
Set the default RTOS system memory manager.
memory_resource * malloc_resource(void) noexcept
Get the address of a memory manager based on POSIX malloc().
memory_resource * get_resource_typed< thread >(void) noexcept
bool operator==(const memory_resource &lhs, const memory_resource &rhs) noexcept
Compare the memory_resource instances for equality.
std::unique_ptr< T, allocator_deleter< allocator_typed< T, U > > > unique_ptr
Type of a RTOS unique pointer to objects of type T.
memory_resource * set_resource_typed< condition_variable >(memory_resource *res) noexcept
memory_resource * set_resource_typed(memory_resource *res) noexcept
Function template to set a memory resource.
memory_resource * set_resource_typed< message_queue >(memory_resource *res) noexcept
memory_resource * get_default_resource(void) noexcept
Get the default RTOS system memory manager.
memory_resource * set_resource_typed< memory_pool >(memory_resource *res) noexcept
memory_resource * get_resource_typed< semaphore >(void) noexcept
memory_resource * set_resource_typed< event_flags >(memory_resource *res) noexcept
bool operator!=(const memory_resource &lhs, const memory_resource &rhs) noexcept
Compare the memory_resource instances for inequality.
memory_resource * get_resource_typed< timer >(void) noexcept
memory_resource * set_resource_typed< mutex >(memory_resource *res) noexcept
auto allocate_unique(const A &allocator, Args &&... args)
Function template to allocate a unique pointer.
memory_resource * set_resource_typed< semaphore >(memory_resource *res) noexcept
allocator_stateless_default_resource< T > allocator
Type of allocator used by the system objects. Must be stateless.
memory_resource * set_resource_typed< thread >(memory_resource *res) noexcept
memory_resource * get_resource_typed< message_queue >(void) noexcept
memory_resource * get_resource_typed< memory_pool >(void) noexcept
memory_resource * get_resource_typed< mutex >(void) noexcept
memory_resource * get_resource_typed< event_flags >(void) noexcept
memory_resource * set_resource_typed< timer >(memory_resource *res) noexcept
rtos::memory::memory_resource memory_resource
void __throw_system_error(int ev, const char *what_arg)
void __throw_bad_alloc(void)
constexpr std::size_t align_size(std::size_t size, std::size_t align) noexcept
Helper function to align size values.
constexpr std::size_t max(std::size_t a, std::size_t b)
Define a rebind template.