diff options
Diffstat (limited to 'ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h')
-rw-r--r-- | ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h b/ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h new file mode 100644 index 000000000..1f9229772 --- /dev/null +++ b/ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h @@ -0,0 +1,385 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_KERNEl_3_ +#define DLIB_MEMORY_MANAGER_KERNEl_3_ + +#include "../algs.h" +#include "memory_manager_kernel_abstract.h" +#include "../assert.h" +#include <new> +#include "memory_manager_kernel_2.h" +#include "../binary_search_tree/binary_search_tree_kernel_2.h" + + +namespace dlib +{ + + template < + typename T, + unsigned long chunk_size + > + class memory_manager_kernel_3 + { + /*! + INITIAL VALUE + allocations == 0 + next == 0 + first_chunk == 0 + bst_of_arrays == 0 + + REQUIREMENTS ON chunk_size + chunk_size is the number of items of type T we will allocate at a time. so + it must be > 0. + + CONVENTION + This memory manager implementation allocates memory in blocks of chunk_size*sizeof(T) + bytes. All the sizeof(T) subblocks are kept in a linked list of free memory blocks + and are given out whenever an allocation request occurs. Also, memory is not freed + until this object is destructed. + + + + allocations == get_number_of_allocations() + + - if (next != 0) then + - next == the next pointer to return from allocate() + and next == pointer to the first node in a linked list. each node + is one item in the memory pool. + - the last node in the linked list has next set to 0 + - else + - we need to call new to get the next pointer to return from allocate() + + - if (arrays != 0) then + - someone has called allocate_array() + - (*arrays)[size] == an array of size bytes of memory + + - if (first_chunk != 0) then + - first_chunk == the first node in a linked list that contains pointers + to all the chunks we have ever allocated. The last link in the list + has its next pointer set to 0. + !*/ + + union node + { + node* next; + char item[sizeof(T)]; + }; + + struct chunk_node + { + node* chunk; + chunk_node* next; + }; + + + typedef binary_search_tree_kernel_2< + size_t, + char*, + memory_manager_kernel_2<char,5> + > bst_of_arrays; + + public: + + typedef T type; + + template <typename U> + struct rebind { + typedef memory_manager_kernel_3<U,chunk_size> other; + }; + + + memory_manager_kernel_3( + ) : + allocations(0), + next(0), + first_chunk(0), + arrays(0) + { + // You FOOL! You can't have a zero chunk_size. + COMPILE_TIME_ASSERT(chunk_size > 0); + } + + virtual ~memory_manager_kernel_3( + ) + { + if (allocations == 0) + { + while (first_chunk != 0) + { + chunk_node* temp = first_chunk; + first_chunk = first_chunk->next; + // delete the memory chunk + ::operator delete ( static_cast<void*>(temp->chunk)); + // delete the chunk_node + delete temp; + } + } + + if (arrays) + { + arrays->reset(); + while (arrays->move_next()) + { + ::operator delete (arrays->element().value()); + } + delete arrays; + } + } + + unsigned long get_number_of_allocations ( + ) const { return allocations; } + + T* allocate_array ( + unsigned long size + ) + { + size_t block_size = sizeof(T)*size + sizeof(size_t)*2; + + // make sure we have initialized the arrays object. + if (arrays == 0) + { + arrays = new bst_of_arrays; + } + + char* temp; + + // see if we have a suitable block of memory already. + arrays->position_enumerator(block_size); + if (arrays->current_element_valid()) + { + // we have a suitable block of memory already so use that one. + arrays->remove_current_element(block_size,temp); + } + else + { + temp = static_cast<char*>(::operator new(block_size)); + } + + reinterpret_cast<size_t*>(temp)[0] = block_size; + reinterpret_cast<size_t*>(temp)[1] = size; + temp += sizeof(size_t)*2; + + try + { + initialize_array(reinterpret_cast<T*>(temp),size); + } + catch (...) + { + // something was thrown while we were initializing the array so + // stick our memory block into arrays and rethrow the exception + temp -= sizeof(size_t)*2; + arrays->add(block_size,temp); + throw; + } + + ++allocations; + return reinterpret_cast<T*>(temp); + } + + void deallocate_array ( + T* item + ) + { + char* temp = reinterpret_cast<char*>(item); + temp -= sizeof(size_t)*2; + size_t block_size = reinterpret_cast<size_t*>(temp)[0]; + size_t size = reinterpret_cast<size_t*>(temp)[1]; + + deinitialize_array(item,size); + + arrays->add(block_size,temp); + + --allocations; + } + + T* allocate ( + ) + { + T* temp; + if (next != 0) + { + temp = reinterpret_cast<T*>(next); + node* n = next->next; + + try + { + // construct this new T object with placement new. + new (static_cast<void*>(temp))T(); + } + catch (...) + { + next->next = n; + throw; + } + + next = n; + } + else + { + // the linked list is empty so we need to allocate some more memory + node* block = static_cast<node*>(::operator new (sizeof(node)*chunk_size)); + + // the first part of this block can be our new object + temp = reinterpret_cast<T*>(block); + + try + { + // construct this new T object with placement new. + new (static_cast<void*>(temp))T(); + } + catch (...) + { + // construction of the new object threw so delete the block of memory + ::operator delete ( static_cast<void*>(block)); + throw; + } + + // allocate a new chunk_node + chunk_node* chunk; + try {chunk = new chunk_node; } + catch (...) + { + temp->~T(); + ::operator delete ( static_cast<void*>(block)); + throw; + } + + // add this block into the chunk list + chunk->chunk = block; + chunk->next = first_chunk; + first_chunk = chunk; + + + ++block; + // now add the rest of the block into the linked list of free nodes. + for (unsigned long i = 0; i < chunk_size-1; ++i) + { + block->next = next; + next = block; + ++block; + } + + } + + + ++allocations; + return temp; + } + + void deallocate ( + T* item + ) + { + --allocations; + item->~T(); + + // add this memory into our linked list. + node* temp = reinterpret_cast<node*>(item); + temp->next = next; + next = temp; + } + + void swap ( + memory_manager_kernel_3& item + ) + { + exchange(allocations,item.allocations); + exchange(next,item.next); + exchange(first_chunk,item.first_chunk); + exchange(arrays,item.arrays); + } + + private: + + // data members + unsigned long allocations; + node* next; + + chunk_node* first_chunk; + bst_of_arrays* arrays; + + + void initialize_array ( + T* array, + size_t size + ) const + { + size_t i; + try + { + for (i = 0; i < size; ++i) + { + // construct this new T object with placement new. + new (static_cast<void*>(array+i))T(); + } + } + catch (...) + { + // Catch any exceptions thrown during the construction process + // and then destruct any T objects that actually were successfully + // constructed. + for (size_t j = 0; j < i; ++j) + { + array[i].~T(); + } + throw; + } + } + + void deinitialize_array ( + T* array, + size_t size + ) const + { + for (size_t i = 0; i < size; ++i) + { + array[i].~T(); + } + } + + // don't do any initialization for the built in types + void initialize_array(unsigned char*, size_t) {} + void deinitialize_array(unsigned char*, size_t) {} + void initialize_array(signed char*, size_t) {} + void deinitialize_array(signed char*, size_t) {} + void initialize_array(char*, size_t) {} + void deinitialize_array(char*, size_t) {} + void initialize_array(int*, size_t) {} + void deinitialize_array(int*, size_t) {} + void initialize_array(unsigned int*, size_t) {} + void deinitialize_array(unsigned int*, size_t) {} + void initialize_array(unsigned long*, size_t) {} + void deinitialize_array(unsigned long*, size_t) {} + void initialize_array(long*, size_t) {} + void deinitialize_array(long*, size_t) {} + void initialize_array(float*, size_t) {} + void deinitialize_array(float*, size_t) {} + void initialize_array(double*, size_t) {} + void deinitialize_array(double*, size_t) {} + void initialize_array(short*, size_t) {} + void deinitialize_array(short*, size_t) {} + void initialize_array(unsigned short*, size_t) {} + void deinitialize_array(unsigned short*, size_t) {} + + + + // restricted functions + memory_manager_kernel_3(memory_manager_kernel_3&); // copy constructor + memory_manager_kernel_3& operator=(memory_manager_kernel_3&); // assignment operator + }; + + template < + typename T, + unsigned long chunk_size + > + inline void swap ( + memory_manager_kernel_3<T,chunk_size>& a, + memory_manager_kernel_3<T,chunk_size>& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MEMORY_MANAGER_KERNEl_3_ + |