We have a huge legacy code base which is multithreaded and uses vectors extensively. To cut down the time spent in dynamic memory allocation, we are moving to a pools. The plan is to use Boost small vector with a custom allocator. The custom allocator will create a thread local pool per each container type. I have implemented a custom allocator based on the above idea and tested it. For some reason, the code falls in an infinite pattern inside find_prev method in Boost simple segregated storage. There are lots of places where there is a nesting of containers, like vector>> etc. Is this the right way of defining allocator ??
template<typename T, typename allocatorType>
class customAllocator
{
public:
static thread_local allocatorType *_allocator;
typedef T value_type;
typedef allocatorType allocator_Type;
template <class X> struct rebind
{
typedef customAllocator<X, allocatorType> other;
};
customAllocator()
{
_allocator = new allocatorType;
assert(_allocator);
return;
}
~customAllocator()
{
delete _allocator;
_allocator = nullptr;
return;
}
template<class X, class Y> customAllocator(const customAllocator<X, Y>& other)
{
_allocator = other._allocator;
return;
}
template<class X, class Y> customAllocator(customAllocator<X, Y>&& other)
{
_allocator = other._allocator;
other._allocator = nullptr;
return;
}
template<class X, class Y> customAllocator& operator=(const customAllocator<X, Y>& other)
{
_allocator = other._allocator;
return *this;
}
template<class X, class Y> customAllocator& operator=(customAllocator<X, Y>&& other)
{
_allocator = other._allocator;
other._allocator = nullptr;
return *this;
}
T* allocate(size_t n)
{
return _allocator->allocate(n * sizeof(T));
}
void deallocate(T* ptr, size_t n)
{
_allocator->deallocate(ptr, n);
return;
}
template<class X, class Y> bool operator==(const customAllocator<X, Y>& other) const noexcept
{ return (*this._allocator == other.allocator); }
template<class X, class Y> bool operator!=(const customAllocator<X, Y>& other) const noexcept
{ return !(*this._allocator == other._allocator); }
};
template <typename T1, typename T2>
thread_local T2 *customAllocator<T1, T2>::_allocator = nullptr;
using smallVector = boost::container::small_vector<
T,
DEFAULT_SMALL_VECTOR_LENGTH,
customAllocator<T,
boost::pool_allocator<
T,
boost::default_user_allocator_new_delete,
boost::details::pool::null_mutex,
2,
4
>>>;
Aucun commentaire:
Enregistrer un commentaire