Initial Commit - Lesson 31 (Commit #1)
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
// 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_1_
|
||||
#define DLIB_MEMORY_MANAGER_KERNEl_1_
|
||||
|
||||
#include "../algs.h"
|
||||
#include "memory_manager_kernel_abstract.h"
|
||||
#include "../assert.h"
|
||||
#include <new>
|
||||
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
template <
|
||||
typename T,
|
||||
size_t max_pool_size
|
||||
>
|
||||
class memory_manager_kernel_1
|
||||
{
|
||||
/*!
|
||||
INITIAL VALUE
|
||||
allocations == 0
|
||||
next == 0
|
||||
pool_size == 0
|
||||
|
||||
REQUIREMENTS ON max_pool_size
|
||||
max_pool_size is the maximum number of nodes we will keep in our linked list at once.
|
||||
So you can put any value in for this argument.
|
||||
|
||||
CONVENTION
|
||||
This memory manager implementation allocates T objects one at a time when there are
|
||||
allocation requests. Then when there is a deallocate request the returning T object
|
||||
is place into a list of free blocks if that list has less than max_pool_size
|
||||
blocks in it. subsequent allocation requests will be serviced by drawing from the
|
||||
free list whenever it isn't empty.
|
||||
|
||||
|
||||
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
|
||||
- pool_size == the number of nodes in the linked list
|
||||
- pool_size <= max_pool_size
|
||||
- else
|
||||
- we need to call new to get the next pointer to return from allocate()
|
||||
|
||||
!*/
|
||||
|
||||
union node
|
||||
{
|
||||
node* next;
|
||||
char item[sizeof(T)];
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
typedef memory_manager_kernel_1<U,max_pool_size> other;
|
||||
};
|
||||
|
||||
|
||||
memory_manager_kernel_1(
|
||||
) :
|
||||
allocations(0),
|
||||
next(0),
|
||||
pool_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~memory_manager_kernel_1(
|
||||
)
|
||||
{
|
||||
|
||||
while (next != 0)
|
||||
{
|
||||
node* temp = next;
|
||||
next = next->next;
|
||||
::operator delete ( static_cast<void*>(temp));
|
||||
}
|
||||
}
|
||||
|
||||
size_t get_number_of_allocations (
|
||||
) const { return allocations; }
|
||||
|
||||
T* allocate_array (
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
T* temp = new T[size];
|
||||
++allocations;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void deallocate_array (
|
||||
T* item
|
||||
)
|
||||
{
|
||||
--allocations;
|
||||
delete [] item;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
--pool_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = static_cast<T*>(::operator new(sizeof(node)));
|
||||
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*>(temp));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
++allocations;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void deallocate (
|
||||
T* item
|
||||
)
|
||||
{
|
||||
--allocations;
|
||||
item->~T();
|
||||
|
||||
if (pool_size >= max_pool_size)
|
||||
{
|
||||
::operator delete ( static_cast<void*>(item));
|
||||
return;
|
||||
}
|
||||
|
||||
// add this memory chunk into our linked list.
|
||||
node* temp = reinterpret_cast<node*>(item);
|
||||
temp->next = next;
|
||||
next = temp;
|
||||
++pool_size;
|
||||
}
|
||||
|
||||
void swap (
|
||||
memory_manager_kernel_1& item
|
||||
)
|
||||
{
|
||||
exchange(allocations,item.allocations);
|
||||
exchange(next,item.next);
|
||||
exchange(pool_size,item.pool_size);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// data members
|
||||
size_t allocations;
|
||||
node* next;
|
||||
size_t pool_size;
|
||||
|
||||
// restricted functions
|
||||
memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor
|
||||
memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class memory_manager_kernel_1<T,0>
|
||||
{
|
||||
/*!
|
||||
INITIAL VALUE
|
||||
allocations == 0
|
||||
|
||||
CONVENTION
|
||||
This memory manager just calls new and delete directly so it doesn't
|
||||
really do anything.
|
||||
|
||||
allocations == get_number_of_allocations()
|
||||
!*/
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
typedef memory_manager_kernel_1<U,0> other;
|
||||
};
|
||||
|
||||
|
||||
memory_manager_kernel_1(
|
||||
) :
|
||||
allocations(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~memory_manager_kernel_1(
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
size_t get_number_of_allocations (
|
||||
) const { return allocations; }
|
||||
|
||||
T* allocate_array (
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
T* temp = new T[size];
|
||||
++allocations;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void deallocate_array (
|
||||
T* item
|
||||
)
|
||||
{
|
||||
--allocations;
|
||||
delete [] item;
|
||||
}
|
||||
|
||||
T* allocate (
|
||||
)
|
||||
{
|
||||
T* temp = new T;
|
||||
++allocations;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void deallocate (
|
||||
T* item
|
||||
)
|
||||
{
|
||||
delete item;
|
||||
--allocations;
|
||||
}
|
||||
|
||||
void swap (
|
||||
memory_manager_kernel_1& item
|
||||
)
|
||||
{
|
||||
exchange(allocations,item.allocations);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// data members
|
||||
size_t allocations;
|
||||
|
||||
// restricted functions
|
||||
memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor
|
||||
memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T,
|
||||
size_t max_pool_size
|
||||
>
|
||||
inline void swap (
|
||||
memory_manager_kernel_1<T,max_pool_size>& a,
|
||||
memory_manager_kernel_1<T,max_pool_size>& b
|
||||
) { a.swap(b); }
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_MEMORY_MANAGER_KERNEl_1_
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
// 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_2_
|
||||
#define DLIB_MEMORY_MANAGER_KERNEl_2_
|
||||
|
||||
#include "../algs.h"
|
||||
#include "memory_manager_kernel_abstract.h"
|
||||
#include "../assert.h"
|
||||
#include <new>
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
template <
|
||||
typename T,
|
||||
size_t chunk_size
|
||||
>
|
||||
class memory_manager_kernel_2
|
||||
{
|
||||
/*!
|
||||
INITIAL VALUE
|
||||
allocations == 0
|
||||
next == 0
|
||||
first_chunk == 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.
|
||||
|
||||
Note that array allocations are not memory managed.
|
||||
|
||||
|
||||
|
||||
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 (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;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
typedef memory_manager_kernel_2<U,chunk_size> other;
|
||||
};
|
||||
|
||||
|
||||
memory_manager_kernel_2(
|
||||
) :
|
||||
allocations(0),
|
||||
next(0),
|
||||
first_chunk(0)
|
||||
{
|
||||
// You FOOL! You can't have a zero chunk_size.
|
||||
COMPILE_TIME_ASSERT(chunk_size > 0);
|
||||
}
|
||||
|
||||
virtual ~memory_manager_kernel_2(
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t get_number_of_allocations (
|
||||
) const { return allocations; }
|
||||
|
||||
T* allocate_array (
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
T* temp = new T[size];
|
||||
++allocations;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void deallocate_array (
|
||||
T* item
|
||||
)
|
||||
{
|
||||
--allocations;
|
||||
delete [] item;
|
||||
}
|
||||
|
||||
T* allocate (
|
||||
)
|
||||
{
|
||||
T* temp = 0;
|
||||
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 = 0;
|
||||
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 (size_t 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_2& item
|
||||
)
|
||||
{
|
||||
exchange(allocations,item.allocations);
|
||||
exchange(next,item.next);
|
||||
exchange(first_chunk,item.first_chunk);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// data members
|
||||
size_t allocations;
|
||||
node* next;
|
||||
|
||||
chunk_node* first_chunk;
|
||||
|
||||
|
||||
|
||||
|
||||
// restricted functions
|
||||
memory_manager_kernel_2(memory_manager_kernel_2&); // copy constructor
|
||||
memory_manager_kernel_2& operator=(memory_manager_kernel_2&); // assignment operator
|
||||
};
|
||||
|
||||
template <
|
||||
typename T,
|
||||
size_t chunk_size
|
||||
>
|
||||
inline void swap (
|
||||
memory_manager_kernel_2<T,chunk_size>& a,
|
||||
memory_manager_kernel_2<T,chunk_size>& b
|
||||
) { a.swap(b); }
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_MEMORY_MANAGER_KERNEl_2_
|
||||
|
||||
@@ -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,
|
||||
size_t 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;
|
||||
}
|
||||
}
|
||||
|
||||
size_t get_number_of_allocations (
|
||||
) const { return allocations; }
|
||||
|
||||
T* allocate_array (
|
||||
size_t 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 (size_t 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
|
||||
size_t 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,
|
||||
size_t 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_
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
// Copyright (C) 2004 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#undef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
|
||||
#ifdef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
|
||||
|
||||
#include "../algs.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class memory_manager
|
||||
{
|
||||
/*!
|
||||
REQUIREMENTS ON T
|
||||
T must have a default constructor.
|
||||
|
||||
INITIAL VALUE
|
||||
get_number_of_allocations() == 0
|
||||
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This object represents some kind of memory manager or memory pool.
|
||||
!*/
|
||||
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
typedef memory_manager<U> other;
|
||||
};
|
||||
|
||||
memory_manager(
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #*this is properly initialized
|
||||
throws
|
||||
- std::bad_alloc
|
||||
!*/
|
||||
|
||||
virtual ~memory_manager(
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- if (get_number_of_allocations() == 0) then
|
||||
- all resources associated with *this have been released.
|
||||
- else
|
||||
- The memory still allocated will not be deleted and this
|
||||
causes a memory leak.
|
||||
!*/
|
||||
|
||||
size_t get_number_of_allocations (
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns the current number of outstanding allocations
|
||||
!*/
|
||||
|
||||
T* allocate (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- allocates a new object of type T and returns a pointer to it.
|
||||
- #get_number_of_allocations() == get_number_of_allocations() + 1
|
||||
throws
|
||||
- std::bad_alloc or any exception thrown by T's constructor.
|
||||
If this exception is thrown then the call to allocate()
|
||||
has no effect on #*this.
|
||||
!*/
|
||||
|
||||
void deallocate (
|
||||
T* item
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- item == is a pointer to memory that was obtained from a call to
|
||||
this->allocate(). (i.e. you can't deallocate a pointer you
|
||||
got from a different memory_manager instance.)
|
||||
- the memory pointed to by item hasn't already been deallocated.
|
||||
ensures
|
||||
- deallocates the object pointed to by item
|
||||
- #get_number_of_allocations() == get_number_of_allocations() - 1
|
||||
!*/
|
||||
|
||||
T* allocate_array (
|
||||
size_t size
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- allocates a new array of size objects of type T and returns a
|
||||
pointer to it.
|
||||
- #get_number_of_allocations() == get_number_of_allocations() + 1
|
||||
throws
|
||||
- std::bad_alloc or any exception thrown by T's constructor.
|
||||
If this exception is thrown then the call to allocate()
|
||||
has no effect on #*this.
|
||||
!*/
|
||||
|
||||
void deallocate_array (
|
||||
T* item
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- item == is a pointer to memory that was obtained from a call to
|
||||
this->allocate_array(). (i.e. you can't deallocate a pointer you
|
||||
got from a different memory_manager instance and it must be an
|
||||
array.)
|
||||
- the memory pointed to by item hasn't already been deallocated.
|
||||
ensures
|
||||
- deallocates the array pointed to by item
|
||||
- #get_number_of_allocations() == get_number_of_allocations() - 1
|
||||
!*/
|
||||
|
||||
void swap (
|
||||
memory_manager& item
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- swaps *this and item
|
||||
!*/
|
||||
|
||||
private:
|
||||
|
||||
// restricted functions
|
||||
memory_manager(memory_manager&); // copy constructor
|
||||
memory_manager& operator=(memory_manager&); // assignment operator
|
||||
};
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
inline void swap (
|
||||
memory_manager<T>& a,
|
||||
memory_manager<T>& b
|
||||
) { a.swap(b); }
|
||||
/*!
|
||||
provides a global swap function
|
||||
!*/
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
|
||||
|
||||
Reference in New Issue
Block a user