summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:20:02 +0000
commit58daab21cd043e1dc37024a7f99b396788372918 (patch)
tree96771e43bb69f7c1c2b0b4f7374cb74d7866d0cb /ml/dlib/dlib/memory_manager/memory_manager_kernel_3.h
parentReleasing debian version 1.43.2-1. (diff)
downloadnetdata-58daab21cd043e1dc37024a7f99b396788372918.tar.xz
netdata-58daab21cd043e1dc37024a7f99b396788372918.zip
Merging upstream version 1.44.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
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.h385
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_
+