patterncppMinor
Singleton typed memory manager
Viewed 0 times
managertypedsingletonmemory
Problem
For my resources management, I wanted the objects allocated on the heap to be in a contiguous block of memory. Obviously, each data type then has to have their own chunk of memory. I could have used a vector for this, of course, but the resources need to be aligned properly with a given alignment which a vector can't do (for alignments above 16 bytes). In addition, I wanted the allocation to be faster than standard
```
#pragma once
#include
#include
#include
typedef unsigned __int32 U32;
typedef unsigned __int8 U8;
#define TYPED_ALLOCATION
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef TYPED_ALLOCATION
// TODO: the allocation should always return a unique_ptr!
#define MakeUniqueInstance(Type,...) AllocTypedUnique(__VA_ARGS__)
#define MakeSharedInstance(Type,...) AllocTypedShared(__VA_ARGS__)
// This defines a deleter functor in a similar way to the default deleter
template
struct typed_delete
{
typed_delete() = default;
template::value,
void>::type>
typed_delete( const typed_delete& ) = default;
void operator()( _Ty *_Ptr ) const
{
FreeTyped( _Ptr );
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
template
using TypedDeleter = typed_delete ;
// Unfortunately, I haven't found a way to make unique pointers of a base type
// while allocating for a derived type (e.g. unique_ptr pB = TypedAlloc(args),
// therefor I had to use shared pointers.
template
std::unique_ptr> AllocTypedUnique( Args&&... args )
{
return std::unique_ptr>( AllocTyped( args... ) );
}
template
std::shared_ptr AllocTypedShared( Args&&... args )
{
return std::shared_ptr( AllocTyped( args... ), TypedDeleter() );
}
template
T* AllocTyped( Args&&... args )
{
static_assert( sizeof( T ) > 0,
"Cannot allocate memory for zero-size type" );
// Allocate a chunk from the typed memory pool
T* p = TypedAllo
new.```
#pragma once
#include
#include
#include
typedef unsigned __int32 U32;
typedef unsigned __int8 U8;
#define TYPED_ALLOCATION
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef TYPED_ALLOCATION
// TODO: the allocation should always return a unique_ptr!
#define MakeUniqueInstance(Type,...) AllocTypedUnique(__VA_ARGS__)
#define MakeSharedInstance(Type,...) AllocTypedShared(__VA_ARGS__)
// This defines a deleter functor in a similar way to the default deleter
template
struct typed_delete
{
typed_delete() = default;
template::value,
void>::type>
typed_delete( const typed_delete& ) = default;
void operator()( _Ty *_Ptr ) const
{
FreeTyped( _Ptr );
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
template
using TypedDeleter = typed_delete ;
// Unfortunately, I haven't found a way to make unique pointers of a base type
// while allocating for a derived type (e.g. unique_ptr pB = TypedAlloc(args),
// therefor I had to use shared pointers.
template
std::unique_ptr> AllocTypedUnique( Args&&... args )
{
return std::unique_ptr>( AllocTyped( args... ) );
}
template
std::shared_ptr AllocTypedShared( Args&&... args )
{
return std::shared_ptr( AllocTyped( args... ), TypedDeleter() );
}
template
T* AllocTyped( Args&&... args )
{
static_assert( sizeof( T ) > 0,
"Cannot allocate memory for zero-size type" );
// Allocate a chunk from the typed memory pool
T* p = TypedAllo
Solution
Starting on page:
Page( Page&& o )
: page { std::move( o.page ) }
, freeChunks { o.freeChunks } // You want to copy the free chunks.
// Why not move them?
, end { o.end }
{}
Page& operator=( Page&& o )
{
page = std::move( o.page );
freeChunks.swap( o.freeChunks ); // OK works. fine.
// But it looks more logical if you move it.
end = o.end;
return *this;Code Snippets
Page( Page&& o )
: page { std::move( o.page ) }
, freeChunks { o.freeChunks } // You want to copy the free chunks.
// Why not move them?
, end { o.end }
{}
Page& operator=( Page&& o )
{
page = std::move( o.page );
freeChunks.swap( o.freeChunks ); // OK works. fine.
// But it looks more logical if you move it.
end = o.end;
return *this;Context
StackExchange Code Review Q#58188, answer score: 2
Revisions (0)
No revisions yet.