28#ifndef CMSIS_PLUS_RTOS_OS_MEMORY_H_
29#define CMSIS_PLUS_RTOS_OS_MEMORY_H_
33#if defined(__cplusplus)
50#pragma GCC diagnostic push
53#pragma clang diagnostic ignored "-Wc++98-compat"
54#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
75 class critical_section;
85 max (std::size_t a, std::size_t b)
87 return (a >= b) ? a : b;
97 align_size (std::size_t size, std::size_t align)
noexcept
99 return ((size) + (align) - 1L) & ~((align) - 1L);
102 class memory_resource;
173 static constexpr std::size_t
max_align =
alignof(std::max_align_t);
243 deallocate (
void* addr, std::size_t bytes, std::size_t alignment =
263 reset (
void)
noexcept;
481 std::size_t total_bytes_ = 0;
482 std::size_t allocated_bytes_ = 0;
483 std::size_t free_bytes_ = 0;
484 std::size_t allocated_chunks_ = 0;
485 std::size_t free_chunks_ = 0;
486 std::size_t max_allocated_bytes_ = 0;
487 std::size_t allocations_ = 0;
488 std::size_t deallocations_ = 0;
684 template<typename T, typename L, F get_resource>
810 select_on_container_copy_construction (
void)
const noexcept;
813 resource (
void)
const noexcept;
826 template<
typename T1,
typename T2,
typename L, F get_resource>
832 get_resource>& rhs)
noexcept;
834 template<
typename T1,
typename T2,
typename L, F get_resource>
840 get_resource>& rhs)
noexcept;
867 using pointer =
typename allocator_traits::pointer;
955 template<
typename T,
typename A,
typename ... Args>
1076 template<
typename T,
typename U = T>
1087 template<
typename T,
typename U = T>
1088 using unique_ptr = std::unique_ptr<T, allocator_deleter<allocator_typed<T, U>>>;
1113 extern memory_resource* default_resource;
1115 extern memory_resource* resource_thread;
1116 extern memory_resource* resource_condition_variable;
1117 extern memory_resource* resource_event_flags;
1118 extern memory_resource* resource_memory_pool;
1119 extern memory_resource* resource_message_queue;
1120 extern memory_resource* resource_mutex;
1121 extern memory_resource* resource_semaphore;
1122 extern memory_resource* resource_timer;
1136 inline memory_resource*
1140 return default_resource;
1155 return resource_thread;
1170 return resource_condition_variable;
1185 return resource_event_flags;
1200 return resource_memory_pool;
1215 return resource_message_queue;
1230 return resource_mutex;
1245 return resource_semaphore;
1260 return resource_timer;
1317 std::size_t alignment)
noexcept
1320 do_deallocate (addr, bytes, alignment);
1337 return do_is_equal (other);
1346 return do_max_size ();
1371 return do_coalesce ();
1384 out_of_memory_handler_ = handler;
1396 return out_of_memory_handler_;
1402 return total_bytes_;
1408 return allocated_bytes_;
1414 return max_allocated_bytes_;
1426 return allocated_chunks_;
1432 return free_chunks_;
1438 return allocations_;
1444 return deallocations_;
1452 "\ttotal: %u bytes, \n"
1453 "\tallocated: %u bytes in %u chunk(s), \n"
1454 "\tfree: %u bytes in %u chunk(s), \n"
1455 "\tmax: %u bytes, \n"
1456 "\tcalls: %u allocs, %u deallocs\n",
1469 return &lhs == &rhs || lhs.is_equal (rhs);
1475 return !(lhs == rhs);
1480 template<
typename T>
1481 template<
typename U>
1484 allocator_stateless_default_resource<U>
const & other __attribute__((unused)))
noexcept
1489 template<
typename T>
1493 scheduler::critical_section scs;
1496 elements *
sizeof(value_type)));
1499 template<
typename T>
1502 value_type* addr, std::size_t elements)
noexcept
1504 scheduler::critical_section scs;
1507 elements *
sizeof(value_type));
1510 template<
typename T>
1519 template<
typename T,
typename U,
typename L, F get_resource>
1522 allocator_stateless_polymorphic_synchronized<T, L, get_resource>
const & lhs,
1523 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & rhs)
noexcept
1525 return *lhs.resource () == *rhs.resource ();
1528 template<
typename T,
typename U,
typename L, F get_resource>
1531 allocator_stateless_polymorphic_synchronized<T, L, get_resource>
const & lhs,
1532 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & rhs)
noexcept
1534 return !(lhs == rhs);
1539 template<
typename T,
typename L, F get_resource>
1543 trace::printf (
"%s() @%p %p\n", __func__,
this, get_resource ());
1546 template<
typename T,
typename L, F get_resource>
1547 template<
typename U>
1550 allocator_stateless_polymorphic_synchronized<U, L, get_resource>
const & other __attribute__((unused)))
noexcept
1555 template<
typename T,
typename L, F get_resource>
1558 std::size_t elements)
1563 std::size_t ms = max_size ();
1564 if ((ms > 0) && (elements > max_size ()))
1568 "allocator_stateless_polymorphic_synchronized<T>::allocate(size_t n)"
1569 " 'n' exceeds maximum supported size");
1574 std::lock_guard<locker_type> ulk
1577 return static_cast<value_type*
> (get_resource ()->allocate (
1578 elements *
sizeof(value_type),
alignof(value_type)));
1581 template<
typename T,
typename L, F get_resource>
1584 value_type* addr, std::size_t elements)
noexcept
1586 trace::printf (
"%s(%p,%u) @%p\n", __func__, addr, elements,
this);
1589 std::size_t ms = max_size ();
1592 assert (elements <= max_size ());
1597 std::lock_guard<locker_type> ulk
1600 get_resource ()->deallocate (addr, elements *
sizeof(value_type),
1601 alignof(value_type));
1604 template<
typename T,
typename L, F get_resource>
1607 void)
const noexcept
1609 return get_resource ()->max_size () /
sizeof(T);
1613 template<
typename T,
typename L, F get_resource>
1614 inline allocator_stateless_polymorphic_synchronized<T, L, get_resource>
1615 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::select_on_container_copy_construction (
1616 void)
const noexcept
1618 return allocator_stateless_polymorphic_synchronized ();
1621 template<
typename T,
typename L, F get_resource>
1623 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::resource (
1624 void)
const noexcept
1626 return get_resource ();
1632 template<
typename A>
1639 template<
typename A>
1655 template<
typename A>
1657 allocator_deleter<A>::operator() (pointer addr)
const
1661 allocator_type alloc
1665 allocator_traits::destroy (alloc, std::addressof (*addr));
1669 allocator_traits::deallocate (alloc, addr, 1);
1685 template<
typename T,
typename A,
typename ... Args>
1692 using allocator_type = A;
1697 using allocator_traits = std::allocator_traits<A>;
1699 static_assert(std::is_same<typename allocator_traits::value_type, std::remove_cv_t<T>>::value
1700 || std::is_base_of<typename allocator_traits::value_type, std::remove_cv_t<T>>::value,
1701 "Allocator must be of same type or derived.");
1703 static_assert(
sizeof(T) <=
sizeof(
typename allocator_traits::value_type),
1704 "Derived type must not be larger.");
1706 allocator_type alloc
1710 auto p = allocator_traits::allocate (alloc, 1);
1712#if defined(__EXCEPTIONS)
1717 allocator_traits::construct (alloc, std::addressof (*p),
1718 std::forward<Args>(args)...);
1721 using D = allocator_deleter<A>;
1724 return std::unique_ptr<T, D> (p, D (alloc));
1728 allocator_traits::deallocate (alloc, p, 1);
1735 allocator_traits::construct (alloc, std::addressof (*p),
1736 std::forward<Args>(args)...);
1739 using D = allocator_deleter<A>;
1742 return std::unique_ptr<T, D> (p, D (alloc));
1752#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.