Initial commit: project docs and ignore rules
This commit is contained in:
282
memory_manager.h
Normal file
282
memory_manager.h
Normal file
@@ -0,0 +1,282 @@
|
||||
#ifndef MEMORY_MANAGER_H
|
||||
#define MEMORY_MANAGER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Memory pool for embedded systems with limited heap
|
||||
*
|
||||
* This class provides a simple memory pool implementation to avoid
|
||||
* heap fragmentation and provide predictable memory allocation.
|
||||
*/
|
||||
class MemoryPool {
|
||||
private:
|
||||
static const size_t POOL_SIZE = 4096; // 4KB pool
|
||||
static const size_t MAX_BLOCKS = 32;
|
||||
|
||||
struct Block {
|
||||
void* ptr;
|
||||
size_t size;
|
||||
bool in_use;
|
||||
uint32_t magic; // For corruption detection
|
||||
};
|
||||
|
||||
uint8_t pool_memory[POOL_SIZE];
|
||||
Block blocks[MAX_BLOCKS];
|
||||
size_t next_free_offset;
|
||||
uint32_t allocation_count;
|
||||
uint32_t deallocation_count;
|
||||
|
||||
static const uint32_t MAGIC_NUMBER = 0xDEADBEEF;
|
||||
|
||||
public:
|
||||
MemoryPool();
|
||||
~MemoryPool();
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from the pool
|
||||
* @param size Size in bytes to allocate
|
||||
* @return Pointer to allocated memory or nullptr if failed
|
||||
*/
|
||||
void* allocate(size_t size);
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory back to the pool
|
||||
* @param ptr Pointer to memory to deallocate
|
||||
* @return true if successful, false if invalid pointer
|
||||
*/
|
||||
bool deallocate(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief Get memory usage statistics
|
||||
*/
|
||||
struct MemoryStats {
|
||||
size_t total_size;
|
||||
size_t used_size;
|
||||
size_t free_size;
|
||||
uint32_t allocations;
|
||||
uint32_t deallocations;
|
||||
uint32_t active_blocks;
|
||||
};
|
||||
|
||||
MemoryStats getStats() const;
|
||||
|
||||
/**
|
||||
* @brief Check for memory corruption
|
||||
* @return true if memory is intact, false if corruption detected
|
||||
*/
|
||||
bool checkIntegrity() const;
|
||||
|
||||
/**
|
||||
* @brief Reset the entire pool (use with caution!)
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Print memory usage information
|
||||
*/
|
||||
void printStats() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief RAII wrapper for automatic memory management
|
||||
*
|
||||
* This template class provides automatic memory management
|
||||
* using RAII principles for embedded systems.
|
||||
*/
|
||||
template<typename T>
|
||||
class SmartPtr {
|
||||
private:
|
||||
T* ptr_;
|
||||
MemoryPool* pool_;
|
||||
bool owns_memory_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for pool-allocated memory
|
||||
*/
|
||||
explicit SmartPtr(MemoryPool* pool = nullptr)
|
||||
: ptr_(nullptr), pool_(pool), owns_memory_(false) {
|
||||
if (pool_) {
|
||||
ptr_ = static_cast<T*>(pool_->allocate(sizeof(T)));
|
||||
if (ptr_) {
|
||||
new(ptr_) T(); // Placement new
|
||||
owns_memory_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor taking ownership of existing pointer
|
||||
*/
|
||||
SmartPtr(T* ptr, MemoryPool* pool, bool owns = true)
|
||||
: ptr_(ptr), pool_(pool), owns_memory_(owns) {}
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
SmartPtr(SmartPtr&& other) noexcept
|
||||
: ptr_(other.ptr_), pool_(other.pool_), owns_memory_(other.owns_memory_) {
|
||||
other.ptr_ = nullptr;
|
||||
other.owns_memory_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator
|
||||
*/
|
||||
SmartPtr& operator=(SmartPtr&& other) noexcept {
|
||||
if (this != &other) {
|
||||
reset();
|
||||
ptr_ = other.ptr_;
|
||||
pool_ = other.pool_;
|
||||
owns_memory_ = other.owns_memory_;
|
||||
other.ptr_ = nullptr;
|
||||
other.owns_memory_ = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor - automatically cleans up
|
||||
*/
|
||||
~SmartPtr() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete copy constructor and assignment (no copying)
|
||||
*/
|
||||
SmartPtr(const SmartPtr&) = delete;
|
||||
SmartPtr& operator=(const SmartPtr&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Access the managed object
|
||||
*/
|
||||
T* get() const { return ptr_; }
|
||||
T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
|
||||
/**
|
||||
* @brief Check if the pointer is valid
|
||||
*/
|
||||
bool isValid() const { return ptr_ != nullptr; }
|
||||
explicit operator bool() const { return isValid(); }
|
||||
|
||||
/**
|
||||
* @brief Release ownership without destroying
|
||||
*/
|
||||
T* release() {
|
||||
T* temp = ptr_;
|
||||
ptr_ = nullptr;
|
||||
owns_memory_ = false;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the pointer, destroying current object if owned
|
||||
*/
|
||||
void reset() {
|
||||
if (ptr_ && owns_memory_) {
|
||||
ptr_->~T(); // Explicit destructor call
|
||||
if (pool_) {
|
||||
pool_->deallocate(ptr_);
|
||||
}
|
||||
}
|
||||
ptr_ = nullptr;
|
||||
owns_memory_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Buffer management class with bounds checking
|
||||
*/
|
||||
class SafeBuffer {
|
||||
private:
|
||||
uint8_t* data_;
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
MemoryPool* pool_;
|
||||
bool owns_memory_;
|
||||
|
||||
public:
|
||||
SafeBuffer(size_t capacity, MemoryPool* pool = nullptr);
|
||||
~SafeBuffer();
|
||||
|
||||
// Delete copy constructor and assignment
|
||||
SafeBuffer(const SafeBuffer&) = delete;
|
||||
SafeBuffer& operator=(const SafeBuffer&) = delete;
|
||||
|
||||
// Move constructor and assignment
|
||||
SafeBuffer(SafeBuffer&& other) noexcept;
|
||||
SafeBuffer& operator=(SafeBuffer&& other) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Write data to buffer with bounds checking
|
||||
*/
|
||||
bool write(const void* data, size_t size, size_t offset = 0);
|
||||
|
||||
/**
|
||||
* @brief Read data from buffer with bounds checking
|
||||
*/
|
||||
bool read(void* data, size_t size, size_t offset = 0) const;
|
||||
|
||||
/**
|
||||
* @brief Append data to buffer
|
||||
*/
|
||||
bool append(const void* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Clear buffer contents
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief Get buffer information
|
||||
*/
|
||||
uint8_t* data() { return data_; }
|
||||
const uint8_t* data() const { return data_; }
|
||||
size_t size() const { return size_; }
|
||||
size_t capacity() const { return capacity_; }
|
||||
size_t available() const { return capacity_ - size_; }
|
||||
|
||||
/**
|
||||
* @brief Check if buffer is valid
|
||||
*/
|
||||
bool isValid() const { return data_ != nullptr; }
|
||||
};
|
||||
|
||||
// Global memory pool instance
|
||||
extern MemoryPool globalMemoryPool;
|
||||
|
||||
/**
|
||||
* @brief Convenience function to create smart pointers
|
||||
*/
|
||||
template<typename T>
|
||||
SmartPtr<T> makeSmartPtr(MemoryPool* pool = &globalMemoryPool) {
|
||||
return SmartPtr<T>(pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory debugging macros (only active in debug builds)
|
||||
*/
|
||||
#ifdef DEBUG_MEMORY
|
||||
#define MEM_ALLOC(size) globalMemoryPool.allocate(size)
|
||||
#define MEM_FREE(ptr) globalMemoryPool.deallocate(ptr)
|
||||
#define MEM_CHECK() globalMemoryPool.checkIntegrity()
|
||||
#define MEM_STATS() globalMemoryPool.printStats()
|
||||
#else
|
||||
#define MEM_ALLOC(size) globalMemoryPool.allocate(size)
|
||||
#define MEM_FREE(ptr) globalMemoryPool.deallocate(ptr)
|
||||
#define MEM_CHECK() true
|
||||
#define MEM_STATS() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif // MEMORY_MANAGER_H
|
||||
Reference in New Issue
Block a user