12#ifndef CMSIS_PLUS_RTOS_OS_MEMORY_H_
13#define CMSIS_PLUS_RTOS_OS_MEMORY_H_
17#if defined(__cplusplus)
34#pragma GCC diagnostic push
36#pragma clang diagnostic ignored "-Wc++98-compat"
37#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
46#pragma GCC diagnostic push
48#pragma clang diagnostic ignored "-Wreserved-identifier"
52#pragma GCC diagnostic pop
63 class critical_section;
73 max (std::size_t a, std::size_t b)
75 return (a >= b) ? a : b;
85 align_size (std::size_t size, std::size_t align)
noexcept
87 return ((size) + (align)-1L) & ~((align)-1L);
90 class memory_resource;
152#pragma GCC diagnostic push
153#if defined(__clang__)
154#elif defined(__GNUC__)
155#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
156#pragma GCC diagnostic ignored "-Wsuggest-final-types"
166 static constexpr std::size_t
max_align =
alignof (std::max_align_t);
237 std::size_t alignment =
max_align)
noexcept;
256 reset (
void)
noexcept;
404 std::size_t alignment)
noexcept
474 std::size_t total_bytes_ = 0;
475 std::size_t allocated_bytes_ = 0;
476 std::size_t free_bytes_ = 0;
477 std::size_t allocated_chunks_ = 0;
478 std::size_t free_chunks_ = 0;
479 std::size_t max_allocated_bytes_ = 0;
480 std::size_t allocations_ = 0;
481 std::size_t deallocations_ = 0;
487#pragma GCC diagnostic pop
536 template <
typename T>
568 template <typename U>
663 template <typename L>
679 template <typename T, typename L, F get_resource>
709 template <typename U>
712 U, L, get_resource> const& other) noexcept;
774 template <typename U>
810 select_on_container_copy_construction (
void)
const noexcept;
813 resource (
void)
const noexcept;
825 template <
typename T1,
typename T2,
typename L, F get_resource>
828 T1, L, get_resource>& lhs,
830 T2, L, get_resource>& rhs)
noexcept;
832 template <
typename T1,
typename T2,
typename L, F get_resource>
835 T1, L, get_resource>& lhs,
837 T2, L, get_resource>& rhs)
noexcept;
849 template <
typename A>
863 using pointer =
typename allocator_traits::pointer;
952 template <
typename T,
typename A,
typename... Args>
968 template <
typename T>
976 template <
typename T>
1073 template <
typename T,
typename U = T>
1085 template <
typename T,
typename U = T>
1087 = std::unique_ptr<T, allocator_deleter<allocator_typed<T, U>>>;
1112 extern memory_resource* default_resource;
1114 extern memory_resource* resource_thread;
1115 extern memory_resource* resource_condition_variable;
1116 extern memory_resource* resource_event_flags;
1117 extern memory_resource* resource_memory_pool;
1118 extern memory_resource* resource_message_queue;
1119 extern memory_resource* resource_mutex;
1120 extern memory_resource* resource_semaphore;
1121 extern memory_resource* resource_timer;
1135 inline memory_resource*
1139 return default_resource;
1154 return resource_thread;
1169 return resource_condition_variable;
1184 return resource_event_flags;
1199 return resource_memory_pool;
1214 return resource_message_queue;
1229 return resource_mutex;
1244 return resource_semaphore;
1259 return resource_timer;
1265 : object_named{ name }
1313 std::size_t alignment)
noexcept
1316 do_deallocate (addr, bytes, alignment);
1333 return do_is_equal (other);
1342 return do_max_size ();
1367 return do_coalesce ();
1380 out_of_memory_handler_ = handler;
1392 return out_of_memory_handler_;
1398 return total_bytes_;
1404 return allocated_bytes_;
1410 return max_allocated_bytes_;
1422 return allocated_chunks_;
1428 return free_chunks_;
1434 return allocations_;
1440 return deallocations_;
1448 "\ttotal: %u bytes, \n"
1449 "\tallocated: %u bytes in %u chunk(s), \n"
1450 "\tfree: %u bytes in %u chunk(s), \n"
1451 "\tmax: %u bytes, \n"
1452 "\tcalls: %u allocs, %u deallocs\n",
1466 return &lhs == &rhs || lhs.is_equal (rhs);
1473 return !(lhs == rhs);
1478 template <
typename T>
1479 template <
typename U>
1482 allocator_stateless_default_resource<U>
const& other
1483 __attribute__ ((unused)))
noexcept
1487 template <
typename T>
1491 scheduler::critical_section scs;
1494 elements *
sizeof (value_type)));
1497 template <
typename T>
1500 value_type* addr, std::size_t elements)
noexcept
1502 scheduler::critical_section scs;
1505 elements *
sizeof (value_type));
1508 template <
typename T>
1517 template <
typename T,
typename U,
typename L, F get_resource>
1519 operator== (allocator_stateless_polymorphic_synchronized<
1520 T, L, get_resource>
const& lhs,
1521 allocator_stateless_polymorphic_synchronized<
1522 U, L, get_resource>
const& rhs)
noexcept
1524 return *lhs.resource () == *rhs.resource ();
1527 template <
typename T,
typename U,
typename L, F get_resource>
1529 operator!= (allocator_stateless_polymorphic_synchronized<
1530 T, L, get_resource>
const& lhs,
1531 allocator_stateless_polymorphic_synchronized<
1532 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<
1551 U, L, get_resource>
const& other
1552 __attribute__ ((unused)))
noexcept
1556 template <
typename T,
typename L, F get_resource>
1557 typename allocator_stateless_polymorphic_synchronized<
1558 T, L, get_resource>::value_type*
1559 allocator_stateless_polymorphic_synchronized<
1560 T, L, get_resource>::allocate (std::size_t elements)
1565 std::size_t ms = max_size ();
1566 if ((ms > 0) && (elements > max_size ()))
1570 "allocator_stateless_polymorphic_synchronized<T>::allocate(size_t n)"
1571 " 'n' exceeds maximum supported size");
1576 std::lock_guard<locker_type> ulk{ lk };
1578 return static_cast<value_type*
> (get_resource ()->allocate (
1579 elements *
sizeof (value_type),
alignof (value_type)));
1582 template <
typename T,
typename L, F get_resource>
1584 allocator_stateless_polymorphic_synchronized<
1585 T, L, get_resource>::deallocate (value_type* addr,
1586 std::size_t elements)
noexcept
1588 trace::printf (
"%s(%p,%u) @%p\n", __func__, addr, elements,
this);
1591 std::size_t ms = max_size ();
1594 assert (elements <= max_size ());
1599 std::lock_guard<locker_type> ulk{ lk };
1601 get_resource ()->deallocate (addr, elements *
sizeof (value_type),
1602 alignof (value_type));
1605 template <
typename T,
typename L, F get_resource>
1607 allocator_stateless_polymorphic_synchronized<
1608 T, L, get_resource>::max_size (
void)
const noexcept
1610 return get_resource ()->max_size () /
sizeof (T);
1614 template<
typename T,
typename L, F get_resource>
1615 inline allocator_stateless_polymorphic_synchronized<T, L, get_resource>
1616 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::select_on_container_copy_construction (
1617 void)
const noexcept
1619 return allocator_stateless_polymorphic_synchronized ();
1622 template<
typename T,
typename L, F get_resource>
1624 allocator_stateless_polymorphic_synchronized<T, L, get_resource>::resource (
1625 void)
const noexcept
1627 return get_resource ();
1633 template <
typename A>
1638 template <
typename A>
1640 const allocator_type& other)
1652 template <
typename A>
1654 allocator_deleter<A>::operator() (pointer addr)
const
1658 allocator_type alloc{ a_ };
1661 allocator_traits::destroy (alloc, std::addressof (*addr));
1665 allocator_traits::deallocate (alloc, addr, 1);
1681 template <
typename T,
typename A,
typename... Args>
1688 using allocator_type = A;
1693 using allocator_traits = std::allocator_traits<A>;
1696 std::is_same<
typename allocator_traits::value_type,
1697 std::remove_cv_t<T>>::value
1698 || std::is_base_of<
typename allocator_traits::value_type,
1699 std::remove_cv_t<T>>::value,
1700 "Allocator must be of same type or derived.");
1702 static_assert (
sizeof (T)
1703 <=
sizeof (
typename allocator_traits::value_type),
1704 "Derived type must not be larger.");
1709 auto p = allocator_traits::allocate (alloc, 1);
1711#if defined(__EXCEPTIONS)
1716 allocator_traits::construct (alloc, std::addressof (*p),
1717 std::forward<Args> (args)...);
1720 using D = allocator_deleter<A>;
1723 return std::unique_ptr<T, D> (p, D (alloc));
1727 allocator_traits::deallocate (alloc, p, 1);
1734 allocator_traits::construct (alloc, std::addressof (*p),
1735 std::forward<Args> (args)...);
1738 using D = allocator_deleter<A>;
1741 return std::unique_ptr<T, D> (p, D (alloc));
1751#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.
Scheduler standard locker.
int printf(const char *format,...)
Write a formatted string to the trace device.
memory_resource * get_resource_typed< condition_variable >(void) noexcept
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
void(*)(void) out_of_memory_handler_t
Type of out of memory handler.
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.