From c0b49f6df3a6c1296b6d2984506c2a03ce044204 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 5 Aug 2019 21:50:30 +0200 Subject: [PATCH 1/5] PoolAllocator: improve alloc when upper limit was reached. --- build/CMakeLists.txt | 1 + include/cppcore/Memory/TPoolAllocator.h | 94 ++++++++++++++++++------- 2 files changed, 69 insertions(+), 26 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index fc3b525..2b89b6f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -14,6 +14,7 @@ option( BUILD_UNITTESTS "Build unit tests." ON ) add_definitions( -DCPPCORE_BUILD ) add_definitions( -D_VARIADIC_MAX=10 ) +add_definitions( -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING=1) INCLUDE_DIRECTORIES( BEFORE ${CMAKE_HOME_DIRECTORY}/.. diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index 2771409..32cbec5 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -52,29 +52,55 @@ class TPoolAllocator { size_t reservedMem() const; size_t freeMem() const; void dumpAllocations(CString & allocs); + void resize(size_t newSize); + TPoolAllocator(const TPoolAllocator&) = delete; + TPoolAllocator(TPoolAllocator&&) = delete; + TPoolAllocator& operator = (const TPoolAllocator&) = delete; + private: - size_t m_poolsize; - T *m_pool; - size_t m_currentIdx; + struct Pool { + size_t m_poolsize; + T* m_pool; + size_t m_currentIdx; + Pool *m_next; + + Pool() + : m_poolsize(0) + , m_pool(nullptr) + , m_currentIdx(0) + , m_next( nullptr ) { + // empty + } + + Pool(size_t numItems, Pool *prev ) + : m_poolsize( numItems ) + , m_pool(nullptr) + , m_currentIdx(0) + , m_next(prev) { + m_pool = new T[m_poolsize]; + } + }; + + Pool *m_first; + Pool *m_current; }; template inline TPoolAllocator::TPoolAllocator() -: m_poolsize(0) -, m_pool(nullptr) -, m_currentIdx(0) { +: m_first( nullptr ) +, m_current( nullptr ) { // empty } template inline TPoolAllocator::TPoolAllocator(size_t numItems) -: m_poolsize(numItems) -, m_pool(nullptr) -, m_currentIdx( 0 ) { - m_pool = new T[m_poolsize]; +: m_first( nullptr ) +, m_current( nullptr ) { + m_first = new Pool( numItems ); + m_current = m_first; } template @@ -85,58 +111,63 @@ TPoolAllocator::~TPoolAllocator() { template inline -T *TPoolAllocator::alloc() { - if ( m_currentIdx == m_poolsize ) { +T *TPoolAllocator::alloc() { + if ( m_current->m_currentIdx == m_current->m_poolsize ) { + m_current->m_next = new Pool(m_first->m_poolsize, m_current ); return nullptr; } - ++m_currentIdx; - return &m_pool[m_currentIdx-1]; + m_current->m_currentIdx++; + return &m_current->m_pool[m_current->m_currentIdx-1]; } template inline void TPoolAllocator::release() { - m_currentIdx = 0; + m_current->m_currentIdx = 0; } template inline void TPoolAllocator::reserve(size_t size) { clear(); - m_pool = new T[ size ]; - m_poolsize = size; + + m_first = new Pool(size, nullptr ); + m_current = m_first; + + m_current->m_pool = new T[ size ]; + m_current->m_poolsize = size; } template inline void TPoolAllocator::clear() { - if (nullptr == m_pool) { + if (nullptr == m_current) { return; } - delete [] m_pool; - m_pool = nullptr; - m_currentIdx = 0; - m_poolsize = 0; + delete [] m_current->m_pool; + m_current->m_pool = nullptr; + m_current->m_currentIdx = 0; + m_current->m_poolsize = 0; } template inline size_t TPoolAllocator::capacity() const { - return m_poolsize; + return m_current->m_poolsize; } template inline size_t TPoolAllocator::reservedMem() const { - return m_poolsize * sizeof(T); + return m_current->m_poolsize * sizeof(T); } template inline size_t TPoolAllocator::freeMem() const { - return m_poolsize - m_currentIdx; + return m_current->m_poolsize - m_current->m_currentIdx; } template @@ -144,8 +175,19 @@ inline void TPoolAllocator::dumpAllocations(CString & allocs) { allocs.clear(); char buffer[512]; - sprintf(buffer, "Number allocations = %d\n", (int)m_currentIdx); + sprintf(buffer, "Number allocations = %d\n", (int)m_current->m_currentIdx); allocs.set(buffer); } +template +inline +void TPoolAllocator::resize(size_t newSize) { + if (newSize < m_poolsize) { + return; + } + + m_current->m_next = new Pool(m_current->m_poolsize, m_current); + m_current = m_current->m_next; +} + } From 623af444cbbf9730a68e8bbec9227a6fca8ce604 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 5 Aug 2019 22:25:29 +0200 Subject: [PATCH 2/5] PoolAllocator: fix some build issues. --- include/cppcore/Memory/TPoolAllocator.h | 57 ++++++++++++++++++------- test/memory/TPoolAllocatorTest.cpp | 4 ++ 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index 32cbec5..079121f 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2016 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -28,17 +28,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace CPPCore { - //------------------------------------------------------------------------------------------------- - /// @class TPoolAllocator - /// @ingroup CPPCore - /// - /// @brief This class implements a simple poll-based allocation scheme. - /// Initially you have to define its size. Each allocation will be done from this initially created - /// pool. You have to release all pooled instances after the usage. - /// This allocation scheme is fast and does no call any new-calls during the lifetime of the - /// allocator. - //------------------------------------------------------------------------------------------------- - template +//------------------------------------------------------------------------------------------------- +/// @class TPoolAllocator +/// @ingroup CPPCore +/// +/// @brief This class implements a simple poll-based allocation scheme. +/// Initially you have to define its size. Each allocation will be done from this initially created +/// pool. You have to release all pooled instances after the usage. +/// This allocation scheme is fast and does no call any new-calls during the lifetime of the +/// allocator. +//------------------------------------------------------------------------------------------------- +template class TPoolAllocator { public: TPoolAllocator(); @@ -84,13 +84,15 @@ class TPoolAllocator { Pool *m_first; Pool *m_current; + size_t m_capacity; }; template inline TPoolAllocator::TPoolAllocator() : m_first( nullptr ) -, m_current( nullptr ) { +, m_current( nullptr ) +, m_capacity( 0L ) { // empty } @@ -112,7 +114,12 @@ TPoolAllocator::~TPoolAllocator() { template inline T *TPoolAllocator::alloc() { + if (nullptr == m_current) { + return nullptr; + } + if ( m_current->m_currentIdx == m_current->m_poolsize ) { + resize(m_current->m_poolsize); m_current->m_next = new Pool(m_first->m_poolsize, m_current ); return nullptr; } @@ -124,6 +131,10 @@ T *TPoolAllocator::alloc() { template inline void TPoolAllocator::release() { + if (nullptr == m_current) { + return; + } + m_current->m_currentIdx = 0; } @@ -155,19 +166,27 @@ void TPoolAllocator::clear() { template inline size_t TPoolAllocator::capacity() const { + if (nullptr == m_current) { + return 0L; + } + return m_current->m_poolsize; } template inline size_t TPoolAllocator::reservedMem() const { - return m_current->m_poolsize * sizeof(T); + return m_capacity; } template inline size_t TPoolAllocator::freeMem() const { - return m_current->m_poolsize - m_current->m_currentIdx; + if (nullptr == m_current) { + return 0L; + } + + return (m_current->m_poolsize - m_current->m_currentIdx)-1; } template @@ -182,7 +201,13 @@ void TPoolAllocator::dumpAllocations(CString & allocs) { template inline void TPoolAllocator::resize(size_t newSize) { - if (newSize < m_poolsize) { + if (newSize < m_current->m_poolsize) { + return; + } + + if (nullptr == m_first) { + m_first = new Pool(newSize, nullptr); + m_current = m_first; return; } diff --git a/test/memory/TPoolAllocatorTest.cpp b/test/memory/TPoolAllocatorTest.cpp index fb46075..3f5f9c6 100644 --- a/test/memory/TPoolAllocatorTest.cpp +++ b/test/memory/TPoolAllocatorTest.cpp @@ -89,3 +89,7 @@ TEST_F(TPoolAllocatorTest, clearTest ) { EXPECT_EQ( allocator.freeMem(), 0u ); } +TEST_F(TPoolAllocatorTest, resizeTest) { + TPoolAllocator allocator; + allocator.resize(100); +} From 3a681e8f1861d5b8b2f58760487dac05aa783fdb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 5 Aug 2019 22:39:58 +0200 Subject: [PATCH 3/5] PoolAllocator: fix some build issues. --- include/cppcore/Memory/TPoolAllocator.h | 2 +- test/container/TArrayTest.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index 079121f..c5cb3db 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -125,7 +125,7 @@ T *TPoolAllocator::alloc() { } m_current->m_currentIdx++; - return &m_current->m_pool[m_current->m_currentIdx-1]; + return &m_current->m_pool[m_current->m_currentIdx]; } template diff --git a/test/container/TArrayTest.cpp b/test/container/TArrayTest.cpp index 00bce1c..468012c 100644 --- a/test/container/TArrayTest.cpp +++ b/test/container/TArrayTest.cpp @@ -65,7 +65,7 @@ TEST_F( TArrayTest, constructTest ) { TEST_F( TArrayTest, constructWithSizeTest) { TArray arrayInstance( 4 ); - EXPECT_EQ( 4, arrayInstance.size() ); + EXPECT_EQ( 4u, arrayInstance.size() ); } TEST_F( TArrayTest, addTest) { @@ -73,7 +73,7 @@ TEST_F( TArrayTest, addTest) { arrayInstance.add( 0.0f ); arrayInstance.add( 1.0f ); - EXPECT_EQ( 2, arrayInstance.size() ); + EXPECT_EQ( 2u, arrayInstance.size() ); EXPECT_EQ( 0.0f, arrayInstance[ 0 ] ); EXPECT_EQ( 1.0f, arrayInstance[ 1 ] ); } @@ -84,13 +84,13 @@ TEST_F( TArrayTest, addItemsTest ) { float data[2] = { 0, 1 }; arrayInstance.add( data, 2 ); - EXPECT_EQ( 3, arrayInstance.size() ); + EXPECT_EQ( 3u, arrayInstance.size() ); EXPECT_EQ( 0.0f, arrayInstance[ 0 ] ); EXPECT_EQ( 0.0f, arrayInstance[ 1 ] ); EXPECT_EQ( 1.0f, arrayInstance[ 2 ] ); arrayInstance.add( nullptr, 0 ); - EXPECT_EQ( 3, arrayInstance.size() ); + EXPECT_EQ( 3u, arrayInstance.size() ); } TEST_F( TArrayTest, accessTest) { From abdb92a53f8a579af5e1ca5036532d4c87594164 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 6 Aug 2019 00:15:16 +0200 Subject: [PATCH 4/5] fix warnings. --- include/cppcore/Memory/TPoolAllocator.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index c5cb3db..b92ff30 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -148,6 +148,8 @@ void TPoolAllocator::reserve(size_t size) { m_current->m_pool = new T[ size ]; m_current->m_poolsize = size; + + m_capacity = size; } template @@ -213,6 +215,7 @@ void TPoolAllocator::resize(size_t newSize) { m_current->m_next = new Pool(m_current->m_poolsize, m_current); m_current = m_current->m_next; + m_capacity += m_current->m_poolsize; } } From 4d5e258d4b1ac91589e620ed025c53e2804d7a05 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 7 Aug 2019 16:41:42 +0200 Subject: [PATCH 5/5] PoolAllocator: Fix the resizing. --- include/cppcore/CPPCoreCommon.h | 8 +- include/cppcore/Common/Variant.h | 7 +- include/cppcore/Memory/TPoolAllocator.h | 104 ++++++++++++----------- include/cppcore/Memory/TStackAllocator.h | 13 ++- test/memory/TPoolAllocatorTest.cpp | 10 ++- 5 files changed, 82 insertions(+), 60 deletions(-) diff --git a/include/cppcore/CPPCoreCommon.h b/include/cppcore/CPPCoreCommon.h index d6851e1..bf2e46e 100644 --- a/include/cppcore/CPPCoreCommon.h +++ b/include/cppcore/CPPCoreCommon.h @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2016 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -24,6 +24,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +#include +#include namespace CPPCore { @@ -81,8 +84,9 @@ void ContainerClear( T & ctr, void( *DeleterFunc )( T & ) = nullptr ) { /// @param name [in] The name of the class. //------------------------------------------------------------------------------------------------- #define CPPCORE_NONE_COPYING( name ) \ -private:\ +public: \ name( const name & ) = delete ;\ + name( name && ) = delete; \ name &operator = ( const name & ) = delete; //------------------------------------------------------------------------------------------------- diff --git a/include/cppcore/Common/Variant.h b/include/cppcore/Common/Variant.h index ded8014..898b260 100644 --- a/include/cppcore/Common/Variant.h +++ b/include/cppcore/Common/Variant.h @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2017 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -87,7 +87,12 @@ class Variant { /// @return TYpe enum of the current dynamic type of the instance. Type getType() const; + /// @brief Will set the payload to the given value. + /// @param value [in] The new given payload. void setByte(unsigned char value); + + /// @brief Will return the current payload as a byte value. + /// @return The byte value. unsigned char getByte() const; /// @brief Sets a new integer value, old values will be released and destroyed. diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index b92ff30..0876b86 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -22,9 +22,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -----------------------------------------------------------------------------------------------*/ #pragma once -#include +#include #include -#include namespace CPPCore { @@ -52,57 +51,62 @@ class TPoolAllocator { size_t reservedMem() const; size_t freeMem() const; void dumpAllocations(CString & allocs); - void resize(size_t newSize); - TPoolAllocator(const TPoolAllocator&) = delete; - TPoolAllocator(TPoolAllocator&&) = delete; - TPoolAllocator& operator = (const TPoolAllocator&) = delete; - + void resize(size_t growSize ); + + CPPCORE_NONE_COPYING(TPoolAllocator) private: struct Pool { size_t m_poolsize; - T* m_pool; + T *m_pool; size_t m_currentIdx; Pool *m_next; Pool() - : m_poolsize(0) + : m_poolsize(0u) , m_pool(nullptr) - , m_currentIdx(0) - , m_next( nullptr ) { + , m_currentIdx(0u) + , m_next(nullptr) { // empty } - Pool(size_t numItems, Pool *prev ) - : m_poolsize( numItems ) + Pool(size_t numItems, Pool *prev) + : m_poolsize(numItems) , m_pool(nullptr) - , m_currentIdx(0) + , m_currentIdx(0u) , m_next(prev) { m_pool = new T[m_poolsize]; } + + ~Pool() { + delete[] m_pool; + m_pool = nullptr; + } + + CPPCORE_NONE_COPYING(Pool) }; - Pool *m_first; - Pool *m_current; + Pool *m_first; + Pool *m_current; size_t m_capacity; }; template inline TPoolAllocator::TPoolAllocator() -: m_first( nullptr ) -, m_current( nullptr ) -, m_capacity( 0L ) { +: m_first(nullptr) +, m_current(nullptr) +, m_capacity(0L) { // empty } template inline TPoolAllocator::TPoolAllocator(size_t numItems) -: m_first( nullptr ) -, m_current( nullptr ) { - m_first = new Pool( numItems ); - m_current = m_first; +: m_first(nullptr) +, m_current(nullptr) { + m_first = new Pool(numItems); + m_current = m_first; } template @@ -113,19 +117,19 @@ TPoolAllocator::~TPoolAllocator() { template inline -T *TPoolAllocator::alloc() { +T *TPoolAllocator::alloc() { if (nullptr == m_current) { return nullptr; } - if ( m_current->m_currentIdx == m_current->m_poolsize ) { + if (m_current->m_currentIdx == m_current->m_poolsize) { resize(m_current->m_poolsize); - m_current->m_next = new Pool(m_first->m_poolsize, m_current ); - return nullptr; } - + + T *ptr(&m_current->m_pool[m_current->m_currentIdx]); m_current->m_currentIdx++; - return &m_current->m_pool[m_current->m_currentIdx]; + + return ptr; } template @@ -142,11 +146,11 @@ template inline void TPoolAllocator::reserve(size_t size) { clear(); - - m_first = new Pool(size, nullptr ); + + m_first = new Pool(size, nullptr); m_current = m_first; - - m_current->m_pool = new T[ size ]; + + m_current->m_pool = new T[size]; m_current->m_poolsize = size; m_capacity = size; @@ -159,10 +163,13 @@ void TPoolAllocator::clear() { return; } - delete [] m_current->m_pool; - m_current->m_pool = nullptr; - m_current->m_currentIdx = 0; - m_current->m_poolsize = 0; + Pool *next(m_first); + while ( nullptr != next) { + Pool *current = next; + next = current->m_next; + delete current; + } + m_current = nullptr; } template @@ -188,7 +195,7 @@ size_t TPoolAllocator::freeMem() const { return 0L; } - return (m_current->m_poolsize - m_current->m_currentIdx)-1; + return (m_current->m_poolsize - m_current->m_currentIdx); } template @@ -196,26 +203,27 @@ inline void TPoolAllocator::dumpAllocations(CString & allocs) { allocs.clear(); char buffer[512]; - sprintf(buffer, "Number allocations = %d\n", (int)m_current->m_currentIdx); + ::sprintf(buffer, "Number allocations = %zu\n", m_current->m_currentIdx); allocs.set(buffer); } template inline -void TPoolAllocator::resize(size_t newSize) { - if (newSize < m_current->m_poolsize) { - return; +void TPoolAllocator::resize(size_t growSize) { + if (nullptr != m_current) { + if (growSize < m_current->m_poolsize) { + return; + } } if (nullptr == m_first) { - m_first = new Pool(newSize, nullptr); + m_first = new Pool(growSize, nullptr); m_current = m_first; - return; + } else { + m_current->m_next = new Pool(growSize, nullptr); + m_current = m_current->m_next; } - - m_current->m_next = new Pool(m_current->m_poolsize, m_current); - m_current = m_current->m_next; m_capacity += m_current->m_poolsize; } -} +} // Namespace CPPCore diff --git a/include/cppcore/Memory/TStackAllocator.h b/include/cppcore/Memory/TStackAllocator.h index dc9fc8a..000b4a9 100644 --- a/include/cppcore/Memory/TStackAllocator.h +++ b/include/cppcore/Memory/TStackAllocator.h @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2016 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -22,9 +22,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -----------------------------------------------------------------------------------------------*/ #pragma once -#include +#include #include -#include namespace CPPCore { @@ -52,11 +51,11 @@ class TStackAllocator { size_t reservedMem() const; size_t freeMem() const; void dumpAllocations( CString & allocs ); - TStackAllocator( const TStackAllocator & ) = delete; - TStackAllocator &operator = ( const TStackAllocator & ) = delete; + + CPPCORE_NONE_COPYING(TStackAllocator) private: - typedef unsigned char byte_t; + using byte_t = unsigned char; struct Header { size_t m_size; }; @@ -171,7 +170,7 @@ inline void TStackAllocator::dumpAllocations( CString & allocs ) { allocs.clear(); char buffer[ 512 ]; - sprintf( buffer, "Number allocations = %d\n", ( int ) m_numAllocs ); + sprintf( buffer, "Number allocations = %zu\n", m_numAllocs ); allocs.set( buffer ); } diff --git a/test/memory/TPoolAllocatorTest.cpp b/test/memory/TPoolAllocatorTest.cpp index 3f5f9c6..f1597d3 100644 --- a/test/memory/TPoolAllocatorTest.cpp +++ b/test/memory/TPoolAllocatorTest.cpp @@ -61,7 +61,7 @@ TEST_F(TPoolAllocatorTest, alloc_access_Test) { } PoolItem *nullItem = allocator.alloc(); - EXPECT_EQ(nullptr, nullItem); + EXPECT_NE(nullptr, nullItem); } TEST_F(TPoolAllocatorTest, countAllocsTest) { @@ -84,7 +84,7 @@ TEST_F(TPoolAllocatorTest, getAllocsTest) { TEST_F(TPoolAllocatorTest, clearTest ) { TPoolAllocator allocator; - allocator.reserve( 100 ); + allocator.reserve( 100u ); allocator.clear(); EXPECT_EQ( allocator.freeMem(), 0u ); } @@ -92,4 +92,10 @@ TEST_F(TPoolAllocatorTest, clearTest ) { TEST_F(TPoolAllocatorTest, resizeTest) { TPoolAllocator allocator; allocator.resize(100); + //allocator.resize(100); + + for (size_t i = 0; i < 200; ++i) { + EXPECT_NE(nullptr, allocator.alloc()); + } + EXPECT_EQ(200u, allocator.reservedMem()); }