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