Bonita Montero
unread,Dec 13, 2019, 5:57:37 AM12/13/19You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
I wrote a class where all the memory allocated from it must come from
a single allocator. I've derived my own allocator from mimalloc to make
it NUMA-aware. So I had the idea of a simple helper-class that is like
uniuqe_ptr but also has a attached allocator. So here it is:
#pragma once
#include <memory>
#include <utility>
#include "cpp_attr.h"
template<typename T, typename Alloc = std::allocator<T>>
class alloc_ptr
{
public:
template<typename ... Args>
alloc_ptr( Alloc const &alloc, Args ... args );
alloc_ptr( alloc_ptr &&other );
~alloc_ptr();
T &operator *();
T *operator ->();
T *release();
void swap( alloc_ptr &other );
T *get();
operator bool();
private:
using t_allocator = typename std::allocator_traits<Alloc>::template
rebind_alloc<T>;
using atraits = std::allocator_traits<t_allocator>;
T *m_object;
[[no_unique_address]]
t_allocator m_alloc;
};
template<typename T, typename Alloc>
template<typename ... Args>
inline
alloc_ptr<T, Alloc>::alloc_ptr( Alloc const &alloc, Args ... args ) :
m_alloc( t_allocator( alloc ) )
{
m_object = atraits::allocate( m_alloc, 1 );
try
{
atraits::construct( m_alloc, m_object, args ... );
}
catch( ... )
{
atraits::deallocate( m_alloc, m_object, 1 );
throw;
}
}
template<typename T, typename Alloc>
inline
alloc_ptr<T, Alloc>::~alloc_ptr()
{
atraits::deallocate( m_alloc, m_object, 1 );
atraits::destroy( m_alloc, m_object );
}
template<typename T, typename Alloc>
inline
alloc_ptr<T, Alloc>::alloc_ptr( alloc_ptr &&other )
{
m_alloc = other.m_alloc;
m_object = other.m_object;
other.m_object = nullptr;
}
template<typename T, typename Alloc>
inline
T &alloc_ptr<T, Alloc>::operator *()
{
return *m_object;
}
template<typename T, typename Alloc>
inline
T *alloc_ptr<T, Alloc>::operator ->()
{
return m_object;
}
template<typename T, typename Alloc>
inline
T *alloc_ptr<T, Alloc>::release()
{
T *object = m_object;
m_object = nullptr;
return object;
}
template<typename T, typename Alloc>
inline
void alloc_ptr<T, Alloc>::swap( alloc_ptr &other )
{
swap( m_alloc, other.m_alloc );
swap( m_object, other.m_object );
}
template<typename T, typename Alloc>
inline
T *alloc_ptr<T, Alloc>::get()
{
return m_object;
}
template<typename T, typename Alloc>
inline
alloc_ptr<T, Alloc>::operator bool()
{
return m_object != nullptr;
}
I'm deriving my own allocator-type with allocator_traits<A>
::rebind_alloc<A2) to have more convenience. So I won't have
to convert my internal allocator on every definition of an
alloc_ptr.