Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
kcenon::monitoring::memory_pool Class Reference

Thread-safe fixed-size block memory allocator. More...

#include <memory_pool.h>

Collaboration diagram for kcenon::monitoring::memory_pool:
Collaboration graph

Public Member Functions

 memory_pool ()
 Default constructor with default configuration.
 
 memory_pool (const memory_pool_config &config)
 Construct with configuration.
 
 ~memory_pool ()
 
 memory_pool (const memory_pool &)=delete
 
memory_pooloperator= (const memory_pool &)=delete
 
 memory_pool (memory_pool &&other) noexcept
 
memory_pooloperator= (memory_pool &&other) noexcept
 
common::Result< void * > allocate ()
 Allocate a memory block.
 
common::VoidResult deallocate (void *ptr)
 Deallocate a memory block.
 
template<typename T , typename... Args>
common::Result< T * > allocate_object (Args &&... args)
 Allocate and construct an object.
 
template<typename T >
common::VoidResult deallocate_object (T *obj)
 Destroy and deallocate an object.
 
size_t available_blocks () const
 Get number of available blocks.
 
size_t total_blocks () const
 Get total number of blocks.
 
size_t block_size () const
 Get block size.
 
const memory_pool_statisticsget_statistics () const
 Get pool statistics.
 
void reset_statistics ()
 Reset statistics.
 

Private Member Functions

void initialize_pool ()
 
bool grow_pool ()
 
bool is_owned_block (void *ptr) const
 
void update_peak_usage ()
 

Private Attributes

memory_pool_config config_
 
size_t block_size_
 
size_t total_blocks_
 
std::vector< void * > free_blocks_
 
std::vector< void * > memory_chunks_
 
std::mutex mutex_
 
memory_pool_statistics stats_
 

Detailed Description

Thread-safe fixed-size block memory allocator.

This pool pre-allocates memory blocks of fixed size for efficient allocation/deallocation without heap fragmentation.

Definition at line 171 of file memory_pool.h.

Constructor & Destructor Documentation

◆ memory_pool() [1/4]

kcenon::monitoring::memory_pool::memory_pool ( )
inline

Default constructor with default configuration.

Definition at line 176 of file memory_pool.h.

176: memory_pool(memory_pool_config{}) {}
memory_pool()
Default constructor with default configuration.

◆ memory_pool() [2/4]

kcenon::monitoring::memory_pool::memory_pool ( const memory_pool_config & config)
inlineexplicit

Construct with configuration.

Parameters
configPool configuration

Definition at line 182 of file memory_pool.h.

183 : config_(config)
184 , block_size_(config.block_size)
185 , total_blocks_(config.initial_blocks) {
187 }

References initialize_pool().

Here is the call graph for this function:

◆ ~memory_pool()

kcenon::monitoring::memory_pool::~memory_pool ( )
inline

Definition at line 189 of file memory_pool.h.

189 {
190 for (auto* chunk : memory_chunks_) {
192 }
193 }
std::vector< void * > memory_chunks_
void aligned_free_impl(void *ptr)
Platform-specific aligned memory deallocation.
Definition memory_pool.h:52

References detail::aligned_free_impl(), and memory_chunks_.

Here is the call graph for this function:

◆ memory_pool() [3/4]

kcenon::monitoring::memory_pool::memory_pool ( const memory_pool & )
delete

◆ memory_pool() [4/4]

kcenon::monitoring::memory_pool::memory_pool ( memory_pool && other)
inlinenoexcept

Definition at line 200 of file memory_pool.h.

201 : config_(other.config_)
202 , block_size_(other.block_size_)
203 , total_blocks_(other.total_blocks_)
204 , free_blocks_(std::move(other.free_blocks_))
205 , memory_chunks_(std::move(other.memory_chunks_))
206 , stats_(std::move(other.stats_)) {
207 other.total_blocks_ = 0;
208 }
std::vector< void * > free_blocks_
memory_pool_statistics stats_

References kcenon::monitoring::other.

Member Function Documentation

◆ allocate()

common::Result< void * > kcenon::monitoring::memory_pool::allocate ( )
inline

Allocate a memory block.

Returns
common::Result<void*> containing pointer to allocated block

Definition at line 230 of file memory_pool.h.

230 {
231 std::lock_guard<std::mutex> lock(mutex_);
232
233 if (free_blocks_.empty()) {
234 // Try to grow the pool
235 if (!grow_pool()) {
237 return common::Result<void*>::err(error_info(monitoring_error_code::resource_unavailable, "Memory pool exhausted").to_common_error());
238 }
239 }
240
241 void* block = free_blocks_.back();
242 free_blocks_.pop_back();
243
246
247 return common::ok(block);
248 }

References kcenon::monitoring::memory_pool_statistics::allocation_failures, free_blocks_, grow_pool(), mutex_, kcenon::monitoring::resource_unavailable, stats_, kcenon::monitoring::memory_pool_statistics::total_allocations, and update_peak_usage().

Referenced by allocate_object(), TEST_F(), TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ allocate_object()

template<typename T , typename... Args>
common::Result< T * > kcenon::monitoring::memory_pool::allocate_object ( Args &&... args)
inline

Allocate and construct an object.

Template Parameters
TThe object type
ArgsConstructor argument types
Parameters
argsConstructor arguments
Returns
common::Result<T*> containing pointer to constructed object

Definition at line 281 of file memory_pool.h.

281 {
282 if (sizeof(T) > block_size_) {
283 return common::Result<T*>::err(error_info(monitoring_error_code::invalid_argument, "Object size exceeds block size").to_common_error());
284 }
285
286 auto result = allocate();
287 if (result.is_err()) {
288 return common::Result<T*>::err(error_info(monitoring_error_code::resource_unavailable, "Failed to allocate memory for object").to_common_error());
289 }
290
291 void* ptr = result.value();
292 T* obj = new (ptr) T(std::forward<Args>(args)...);
293
294 return common::ok(obj);
295 }
common::Result< void * > allocate()
Allocate a memory block.

References allocate(), block_size_, kcenon::monitoring::invalid_argument, and kcenon::monitoring::resource_unavailable.

Referenced by TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ available_blocks()

size_t kcenon::monitoring::memory_pool::available_blocks ( ) const
inline

Get number of available blocks.

Returns
Number of free blocks

Definition at line 317 of file memory_pool.h.

317 {
318 std::lock_guard<std::mutex> lock(mutex_);
319 return free_blocks_.size();
320 }

References free_blocks_, and mutex_.

Referenced by TEST_F(), and TEST_F().

Here is the caller graph for this function:

◆ block_size()

size_t kcenon::monitoring::memory_pool::block_size ( ) const
inline

Get block size.

Returns
Size of each block in bytes

Definition at line 334 of file memory_pool.h.

334 {
335 return block_size_;
336 }

References block_size_.

◆ deallocate()

common::VoidResult kcenon::monitoring::memory_pool::deallocate ( void * ptr)
inline

Deallocate a memory block.

Parameters
ptrPointer to the block to deallocate
Returns
common::VoidResult indicating success or error

Definition at line 255 of file memory_pool.h.

255 {
256 if (ptr == nullptr) {
257 return common::VoidResult::err(error_info(monitoring_error_code::invalid_argument, "Cannot deallocate null pointer").to_common_error());
258 }
259
260 std::lock_guard<std::mutex> lock(mutex_);
261
262 // Verify the pointer belongs to this pool
263 if (!is_owned_block(ptr)) {
264 return common::VoidResult::err(error_info(monitoring_error_code::invalid_argument, "Pointer does not belong to this pool").to_common_error());
265 }
266
267 free_blocks_.push_back(ptr);
269
270 return common::ok();
271 }
bool is_owned_block(void *ptr) const

References free_blocks_, kcenon::monitoring::invalid_argument, is_owned_block(), mutex_, stats_, and kcenon::monitoring::memory_pool_statistics::total_deallocations.

Referenced by deallocate_object(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deallocate_object()

template<typename T >
common::VoidResult kcenon::monitoring::memory_pool::deallocate_object ( T * obj)
inline

Destroy and deallocate an object.

Template Parameters
TThe object type
Parameters
objPointer to the object
Returns
common::VoidResult indicating success or error

Definition at line 304 of file memory_pool.h.

304 {
305 if (obj == nullptr) {
306 return common::VoidResult::err(error_info(monitoring_error_code::invalid_argument, "Cannot deallocate null object").to_common_error());
307 }
308
309 obj->~T();
310 return deallocate(static_cast<void*>(obj));
311 }
common::VoidResult deallocate(void *ptr)
Deallocate a memory block.

References deallocate(), and kcenon::monitoring::invalid_argument.

Referenced by TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_statistics()

const memory_pool_statistics & kcenon::monitoring::memory_pool::get_statistics ( ) const
inline

Get pool statistics.

Returns
Reference to statistics

Definition at line 342 of file memory_pool.h.

342 {
343 return stats_;
344 }

References stats_.

Referenced by TEST_F(), TEST_F(), and TEST_F().

Here is the caller graph for this function:

◆ grow_pool()

bool kcenon::monitoring::memory_pool::grow_pool ( )
inlineprivate

Definition at line 372 of file memory_pool.h.

372 {
374 return false;
375 }
376
377 size_t new_blocks = std::min(total_blocks_, config_.max_blocks - total_blocks_);
378 if (new_blocks == 0) {
379 new_blocks = total_blocks_; // Double the size
380 }
381
382 size_t chunk_size = new_blocks * block_size_;
383 void* chunk = detail::aligned_alloc_impl(config_.alignment, chunk_size);
384
385 if (chunk == nullptr) {
386 return false;
387 }
388
389 memory_chunks_.push_back(chunk);
390
391 char* ptr = static_cast<char*>(chunk);
392 for (size_t i = 0; i < new_blocks; ++i) {
393 free_blocks_.push_back(ptr + i * block_size_);
394 }
395
396 total_blocks_ += new_blocks;
397 return true;
398 }
void * aligned_alloc_impl(size_t alignment, size_t size)
Platform-specific aligned memory allocation.
Definition memory_pool.h:35
size_t alignment
Memory alignment (must be power of 2)
Definition memory_pool.h:71
size_t max_blocks
Maximum number of blocks (0 = unlimited)
Definition memory_pool.h:69

References detail::aligned_alloc_impl(), kcenon::monitoring::memory_pool_config::alignment, block_size_, config_, free_blocks_, kcenon::monitoring::memory_pool_config::max_blocks, memory_chunks_, and total_blocks_.

Referenced by allocate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initialize_pool()

void kcenon::monitoring::memory_pool::initialize_pool ( )
inlineprivate

Definition at line 354 of file memory_pool.h.

354 {
355 size_t chunk_size = total_blocks_ * block_size_;
356 void* chunk = detail::aligned_alloc_impl(config_.alignment, chunk_size);
357
358 if (chunk == nullptr) {
359 throw std::bad_alloc();
360 }
361
362 memory_chunks_.push_back(chunk);
363
364 // Initialize free block list
366 char* ptr = static_cast<char*>(chunk);
367 for (size_t i = 0; i < total_blocks_; ++i) {
368 free_blocks_.push_back(ptr + i * block_size_);
369 }
370 }

References detail::aligned_alloc_impl(), kcenon::monitoring::memory_pool_config::alignment, block_size_, config_, free_blocks_, memory_chunks_, and total_blocks_.

Referenced by memory_pool().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_owned_block()

bool kcenon::monitoring::memory_pool::is_owned_block ( void * ptr) const
inlineprivate

Definition at line 400 of file memory_pool.h.

400 {
401 for (size_t i = 0; i < memory_chunks_.size(); ++i) {
402 char* chunk_start = static_cast<char*>(memory_chunks_[i]);
403 size_t chunk_blocks = (i == 0) ? config_.initial_blocks :
404 ((total_blocks_ - config_.initial_blocks) / (memory_chunks_.size() - 1));
405 char* chunk_end = chunk_start + chunk_blocks * block_size_;
406
407 if (ptr >= chunk_start && ptr < chunk_end) {
408 // Verify alignment
409 size_t offset = static_cast<char*>(ptr) - chunk_start;
410 if (offset % block_size_ == 0) {
411 return true;
412 }
413 }
414 }
415 return false;
416 }
size_t initial_blocks
Initial number of blocks.
Definition memory_pool.h:68

References block_size_, config_, kcenon::monitoring::memory_pool_config::initial_blocks, memory_chunks_, and total_blocks_.

Referenced by deallocate().

Here is the caller graph for this function:

◆ operator=() [1/2]

memory_pool & kcenon::monitoring::memory_pool::operator= ( const memory_pool & )
delete

◆ operator=() [2/2]

memory_pool & kcenon::monitoring::memory_pool::operator= ( memory_pool && other)
inlinenoexcept

Definition at line 210 of file memory_pool.h.

210 {
211 if (this != &other) {
212 for (auto* chunk : memory_chunks_) {
214 }
215 config_ = other.config_;
216 block_size_ = other.block_size_;
217 total_blocks_ = other.total_blocks_;
218 free_blocks_ = std::move(other.free_blocks_);
219 memory_chunks_ = std::move(other.memory_chunks_);
220 stats_ = std::move(other.stats_);
221 other.total_blocks_ = 0;
222 }
223 return *this;
224 }

References detail::aligned_free_impl(), block_size_, config_, free_blocks_, memory_chunks_, kcenon::monitoring::other, stats_, and total_blocks_.

Here is the call graph for this function:

◆ reset_statistics()

void kcenon::monitoring::memory_pool::reset_statistics ( )
inline

Reset statistics.

Definition at line 349 of file memory_pool.h.

349 {
350 stats_.reset();
351 }
void reset()
Reset all statistics.

References kcenon::monitoring::memory_pool_statistics::reset(), and stats_.

Here is the call graph for this function:

◆ total_blocks()

size_t kcenon::monitoring::memory_pool::total_blocks ( ) const
inline

Get total number of blocks.

Returns
Total block count

Definition at line 326 of file memory_pool.h.

326 {
327 return total_blocks_;
328 }

References total_blocks_.

Referenced by TEST_F().

Here is the caller graph for this function:

◆ update_peak_usage()

void kcenon::monitoring::memory_pool::update_peak_usage ( )
inlineprivate

Definition at line 418 of file memory_pool.h.

418 {
419 size_t current_usage = total_blocks_ - free_blocks_.size();
420 size_t peak = stats_.peak_usage.load();
421 while (current_usage > peak) {
422 if (stats_.peak_usage.compare_exchange_weak(peak, current_usage)) {
423 break;
424 }
425 }
426 }

References free_blocks_, kcenon::monitoring::memory_pool_statistics::peak_usage, stats_, and total_blocks_.

Referenced by allocate().

Here is the caller graph for this function:

Member Data Documentation

◆ block_size_

size_t kcenon::monitoring::memory_pool::block_size_
private

◆ config_

memory_pool_config kcenon::monitoring::memory_pool::config_
private

Definition at line 428 of file memory_pool.h.

Referenced by grow_pool(), initialize_pool(), is_owned_block(), and operator=().

◆ free_blocks_

std::vector<void*> kcenon::monitoring::memory_pool::free_blocks_
private

◆ memory_chunks_

std::vector<void*> kcenon::monitoring::memory_pool::memory_chunks_
private

Definition at line 432 of file memory_pool.h.

Referenced by grow_pool(), initialize_pool(), is_owned_block(), operator=(), and ~memory_pool().

◆ mutex_

std::mutex kcenon::monitoring::memory_pool::mutex_
mutableprivate

Definition at line 433 of file memory_pool.h.

Referenced by allocate(), available_blocks(), and deallocate().

◆ stats_

memory_pool_statistics kcenon::monitoring::memory_pool::stats_
mutableprivate

◆ total_blocks_

size_t kcenon::monitoring::memory_pool::total_blocks_
private

The documentation for this class was generated from the following file: