1 #ifndef GUM_TEST_LEARNING_ALLOC_H 2 #define GUM_TEST_LEARNING_ALLOC_H 3 4 #include <vector> 5 #include <utility> 6 #include <new> 7 #include <memory> 8 #include <string> 9 #include <iostream> 10 #include <sstream> 11 12 namespace gum_tests { 13 14 class DebugPoolAlloc { 15 public: DebugPoolAlloc(const std::size_t size)16 DebugPoolAlloc ( const std::size_t size ) 17 : _mempool_ ( new int[size / sizeof(int) + 1 ] ) 18 , _size_ ( size / sizeof(int) + 1 ) { 19 //std::cout << "create a new pool alloc " << _mempool_ << std::endl; 20 } 21 22 DebugPoolAlloc ( const DebugPoolAlloc& ) = delete; 23 DebugPoolAlloc ( DebugPoolAlloc&& ) = delete; 24 ~DebugPoolAlloc()25 ~DebugPoolAlloc () { 26 delete[] _mempool_; 27 } 28 29 DebugPoolAlloc& operator= ( const DebugPoolAlloc& ) = delete; 30 DebugPoolAlloc& operator= ( DebugPoolAlloc&& ) = delete; 31 allocate(const std::size_t nb_bytes)32 int* allocate ( const std::size_t nb_bytes ) { 33 std::size_t nb_int = nb_bytes / sizeof(int); 34 if ( nb_bytes % sizeof(int) ) ++nb_int; 35 if ( _current_index_ + nb_int > _size_ ) 36 throw std::bad_alloc (); 37 int* alloc_pointer = _mempool_ + _current_index_; 38 _allocations_.push_back ( _current_index_ ); 39 _current_index_ += nb_int; 40 41 //std::cout << "LearningAlloc allocated: " << alloc_pointer 42 // << " of size : " << nb_bytes 43 // << " mempool = " << _mempool_ << std::endl; 44 45 return alloc_pointer; 46 } 47 deallocate(int * pointer)48 void deallocate ( int* pointer ) { 49 const std::size_t index = pointer - _mempool_; 50 for ( auto iter = _allocations_.rbegin(); 51 iter != _allocations_.rend(); ++iter ) { 52 if ( *iter == index ) { 53 if ( iter == _allocations_.rbegin() ) 54 _current_index_ = index; 55 _allocations_.erase ( (iter+1).base() ); 56 return; 57 } 58 } 59 60 //std::cout << "LearningAlloc cannot find address: " << pointer 61 // << " in mempool " << _mempool_ << std::endl; 62 throw std::bad_alloc (); 63 } 64 allocatedSize()65 std::size_t allocatedSize () { 66 return _allocations_.size (); 67 } 68 toString()69 std::string toString () const { 70 bool deja = false; 71 std::stringstream str; 72 str << "allocator " << _mempool_ << " = { "; 73 for ( auto index : _allocations_ ) { 74 if ( deja ) str << ", "; 75 else deja = true; 76 str << ( _mempool_ + index ); 77 } 78 str << " }"; 79 return str.str (); 80 } 81 82 83 private: 84 // the pool of memory used 85 int * _mempool_; 86 87 // the size of the pool 88 const std::size_t _size_; 89 90 std::size_t _current_index_ { 0 }; 91 92 // the set of allocation performed as a set sorted of [begin,end) 93 std::vector<std::size_t> _allocations_; 94 95 }; 96 97 98 template <typename T> 99 class LearningAlloc { 100 public: 101 using value_type = T; 102 103 template <typename _Tp1> 104 struct rebind { 105 typedef LearningAlloc<_Tp1> other; 106 }; 107 108 LearningAlloc ( const std::size_t size = 1000 ) _mempool_(new DebugPoolAlloc (size))109 : _mempool_ ( new DebugPoolAlloc ( size ) ) {} 110 LearningAlloc(const LearningAlloc<T> & from)111 LearningAlloc ( const LearningAlloc<T>& from ) 112 : _mempool_ ( from. _mempool_ ) {} 113 114 template <typename U> LearningAlloc(const LearningAlloc<U> & from)115 LearningAlloc( const LearningAlloc<U>& from ) 116 : _mempool_ ( from. _mempool_ ) {} 117 LearningAlloc(LearningAlloc<T> && from)118 LearningAlloc ( LearningAlloc<T>&& from ) 119 : _mempool_ ( from. _mempool_ ) {} 120 ~LearningAlloc()121 ~LearningAlloc () {} 122 123 LearningAlloc<T>& operator= ( const LearningAlloc<T>& from ) { 124 if ( this != &from ) { 125 _mempool_ = from. _mempool_; 126 } 127 return *this; 128 } 129 130 LearningAlloc<T>& operator= ( LearningAlloc<T>&& from ) { 131 if ( this != &from ) { 132 _mempool_ = from. _mempool_; 133 } 134 return *this; 135 } 136 137 template <typename U> 138 bool operator== ( const LearningAlloc<U>& other ) const { 139 return _mempool_.get() == other. _mempool_.get(); 140 } 141 142 template <typename U> 143 bool operator!= ( const LearningAlloc<U>& other ) const { 144 return ! operator== ( other ); 145 } 146 147 allocate(std::size_t num)148 T* allocate( std::size_t num ) { 149 return reinterpret_cast<T*>( _mempool_->allocate ( num * sizeof( T ) ) ); 150 } 151 deallocate(T * p,std::size_t num)152 void deallocate( T* p, std::size_t num ) { 153 _mempool_->deallocate ( reinterpret_cast<int*> ( p ) ); 154 } 155 156 template <typename... Args> construct(T * p,Args &&...args)157 void construct( T* p, Args&&... args ) { 158 ::new ( (void*) p ) T( std::forward<Args>( args )... ); 159 } 160 destroy(T * p)161 void destroy( T* p ) { p->~T(); } 162 allocatedSize()163 std::size_t allocatedSize () { 164 return _mempool_->allocatedSize (); 165 } 166 toString()167 std::string toString () const { 168 return _mempool_->toString (); 169 } 170 171 private: 172 std::shared_ptr<DebugPoolAlloc> _mempool_; 173 174 template <typename U> 175 friend class LearningAlloc; 176 177 }; 178 179 } /* namespace gum_tests */ 180 181 #endif /* GUM_TEST_LEARNING_ALLOC_H */ 182