diff --git a/src/EterLib/BufferPool.cpp b/src/EterLib/BufferPool.cpp new file mode 100644 index 0000000..5f6f30d --- /dev/null +++ b/src/EterLib/BufferPool.cpp @@ -0,0 +1,103 @@ +#include "StdAfx.h" +#include "BufferPool.h" +#include + +CBufferPool::CBufferPool() + : m_totalAllocated(0) +{ +} + +CBufferPool::~CBufferPool() +{ + Clear(); +} + +std::vector CBufferPool::Acquire(size_t minSize) +{ + std::lock_guard lock(m_mutex); + + size_t bestIndex = SIZE_MAX; + size_t bestCapacity = SIZE_MAX; + + for (size_t i = 0; i < m_pool.size(); ++i) + { + if (m_pool[i].capacity >= minSize && m_pool[i].capacity < bestCapacity) + { + bestIndex = i; + bestCapacity = m_pool[i].capacity; + + if (bestCapacity == minSize) + break; + } + } + + if (bestIndex != SIZE_MAX) + { + std::vector result = std::move(m_pool[bestIndex].buffer); + m_pool.erase(m_pool.begin() + bestIndex); + result.clear(); + return result; + } + + std::vector newBuffer; + newBuffer.reserve(minSize); + m_totalAllocated++; + return newBuffer; +} + +void CBufferPool::Release(std::vector&& buffer) +{ + size_t capacity = buffer.capacity(); + + if (capacity == 0 || capacity > MAX_BUFFER_SIZE) + { + return; + } + + std::lock_guard lock(m_mutex); + + if (m_pool.size() >= MAX_POOL_SIZE) + { + auto smallest = std::min_element(m_pool.begin(), m_pool.end(), + [](const TPooledBuffer& a, const TPooledBuffer& b) { + return a.capacity < b.capacity; + }); + + if (smallest != m_pool.end() && smallest->capacity < capacity) + { + *smallest = TPooledBuffer(std::move(buffer)); + } + return; + } + + m_pool.emplace_back(std::move(buffer)); +} + +size_t CBufferPool::GetPoolSize() const +{ + std::lock_guard lock(m_mutex); + return m_pool.size(); +} + +size_t CBufferPool::GetTotalAllocated() const +{ + std::lock_guard lock(m_mutex); + return m_totalAllocated; +} + +size_t CBufferPool::GetTotalMemoryPooled() const +{ + std::lock_guard lock(m_mutex); + size_t total = 0; + for (const auto& buf : m_pool) + { + total += buf.capacity; + } + return total; +} + +void CBufferPool::Clear() +{ + std::lock_guard lock(m_mutex); + m_pool.clear(); +} diff --git a/src/EterLib/BufferPool.h b/src/EterLib/BufferPool.h new file mode 100644 index 0000000..d74b3ea --- /dev/null +++ b/src/EterLib/BufferPool.h @@ -0,0 +1,50 @@ +#ifndef __INC_ETERLIB_BUFFERPOOL_H__ +#define __INC_ETERLIB_BUFFERPOOL_H__ + +#include +#include +#include + +// Buffer pool for file I/O operations +class CBufferPool +{ +public: + CBufferPool(); + ~CBufferPool(); + + // Get buffer with minimum size + std::vector Acquire(size_t minSize); + + // Return buffer to pool + void Release(std::vector&& buffer); + + // Get statistics + size_t GetPoolSize() const; + size_t GetTotalAllocated() const; + size_t GetTotalMemoryPooled() const; // Total bytes held in pool + + // Clear pool + void Clear(); + +private: + struct TPooledBuffer + { + std::vector buffer; + size_t capacity; + + TPooledBuffer(std::vector&& buf) + : buffer(std::move(buf)) + , capacity(buffer.capacity()) + { + } + }; + + std::vector m_pool; + mutable std::mutex m_mutex; + size_t m_totalAllocated; + + static const size_t MAX_POOL_SIZE = 64; + static const size_t MAX_BUFFER_SIZE = 64 * 1024 * 1024; +}; + +#endif // __INC_ETERLIB_BUFFERPOOL_H__