#ifndef FREERTOS_CPP_HEAP_STATS_HPP #define FREERTOS_CPP_HEAP_STATS_HPP #include extern "C" { #include "FreeRTOS.h" } namespace freertos { struct HeapStats final { size_t available_bytes; size_t largest_free_block; size_t smallest_free_block; size_t free_blocks; size_t minimum_ever_free_bytes; size_t successful_allocations; size_t successful_frees; static HeapStats read() noexcept { HeapStats_t raw {}; vPortGetHeapStats( &raw ); return HeapStats { raw.xAvailableHeapSpaceInBytes, raw.xSizeOfLargestFreeBlockInBytes, raw.xSizeOfSmallestFreeBlockInBytes, raw.xNumberOfFreeBlocks, raw.xMinimumEverFreeBytesRemaining, raw.xNumberOfSuccessfulAllocations, raw.xNumberOfSuccessfulFrees }; } bool has_multiple_free_blocks() const noexcept { return free_blocks > 1U; } bool total_exceeds_largest() const noexcept { return available_bytes > largest_free_block; } }; class HeapWatermark final { public: explicit constexpr HeapWatermark( HeapStats baseline ) noexcept : baseline_bytes_ { baseline.available_bytes } { } constexpr size_t baseline_bytes() const noexcept { return baseline_bytes_; } constexpr size_t current_bytes_used( HeapStats sample ) const noexcept { return baseline_bytes_ >= sample.available_bytes ? baseline_bytes_ - sample.available_bytes : 0U; } constexpr size_t peak_bytes_used( HeapStats sample ) const noexcept { return baseline_bytes_ >= sample.minimum_ever_free_bytes ? baseline_bytes_ - sample.minimum_ever_free_bytes : 0U; } constexpr bool recovered( HeapStats sample ) const noexcept { return sample.available_bytes == baseline_bytes_; } private: size_t baseline_bytes_; }; } // namespace freertos #endif