1 #ifndef GUM_TEST_COUNTEDALLOC_H 2 #define GUM_TEST_COUNTEDALLOC_H 3 4 #include <vector> 5 6 namespace gum_tests { 7 8 struct CountedAlloc { 9 static std::size_t allocs; 10 static std::size_t deallocs; 11 nbAllocationsCountedAlloc12 static std::size_t nbAllocations() noexcept { return allocs; } 13 nbDeallocationsCountedAlloc14 static std::size_t nbDeallocations() noexcept { return deallocs; } 15 hasMemoryLeakCountedAlloc16 static bool hasMemoryLeak() noexcept { 17 return allocs != CountedAlloc::deallocs; 18 } 19 }; 20 21 std::size_t CountedAlloc::allocs{0}; 22 std::size_t CountedAlloc::deallocs{0}; 23 24 template <typename T> 25 class DebugCountedAlloc : public CountedAlloc { 26 public: 27 using value_type = T; 28 29 template <typename _Tp1> 30 struct rebind { 31 typedef DebugCountedAlloc<_Tp1> other; 32 }; 33 DebugCountedAlloc()34 DebugCountedAlloc() noexcept {} 35 36 template <typename U> DebugCountedAlloc(const DebugCountedAlloc<U> &)37 DebugCountedAlloc( const DebugCountedAlloc<U>& ) noexcept {} 38 39 bool operator== ( const DebugCountedAlloc<T>& ) const { return true; } 40 41 bool operator!= ( const DebugCountedAlloc<T>& ) const { return false; } 42 allocate(std::size_t num)43 T* allocate( std::size_t num ) { 44 CountedAlloc::allocs += num; 45 return static_cast<T*>(::operator new( num * sizeof( T ) ) ); 46 } 47 deallocate(T * p,std::size_t num)48 void deallocate( T* p, std::size_t num ) { 49 CountedAlloc::deallocs += num; 50 ::operator delete( p ); 51 } 52 53 template <typename... Args> construct(T * p,Args &&...args)54 void construct( T* p, Args&&... args ) { 55 ::new ( (void*) p ) T( std::forward<Args>( args )... ); 56 } 57 destroy(T * p)58 void destroy( T* p ) { p->~T(); } 59 }; 60 61 } /* namespace gum_tests */ 62 63 #endif /* GUM_TEST_COUNTEDALLOC_H */ 64