Reputation: 19431
We have a library that provides a C interface via extern "C"
, and is used from C code, but inside it uses STL containers and some C++ features like RAII for convenience.
Now there is a new requirement that the library should be able to take pointers to a custom malloc
and free
function coming from the client code, and use that for allocations inside. I can place them into the context structure of the library, and use them where needed, but using them with STL is puzzling...
I looked at allocator classes but it seems STL containers must be able to use the default constructors to create the allocator and it seems there is no way to place these pointers into them to let them call through them to do the allocations.
Is it possible to work this around preferably in a thread safe manner (without using globals)?
Upvotes: 2
Views: 466
Reputation: 171263
I looked at allocator classes but it seems STL containers must be able to use the default constructors to create the allocator
That's not true, all containers can be constructed with an allocator explicitly, so you can create your allocator object and then pass it to the container.
extern "C"
{
typedef void* (*allocation_function)(size_t);
typedef void (*deallocation_function)(void*);
}
template<typename T>
class Allocator
{
public:
typedef T value_type;
Allocator(allocation_function alloc, deallocation_function dealloc)
: m_allocate(alloc), m_deallocate(dealloc)
{ }
template<typename U>
Allocator(const Allocator<U>& a)
: m_allocate(a.m_allocate), m_deallocate(a.m_deallocate)
{ }
T* allocate(size_t n)
{ return static_cast<T*>(m_allocate(n * sizeof(T))); }
void deallocate(T* p, size_t)
{ m_deallocate(p); }
private:
template<typename U>
friend class Allocator<U>;
template<typename U>
friend bool operator==(const Allocator<U>&, const Allocator<U>&);
allocation_function m_allocate;
deallocation_function m_deallocate;
};
template<typename T>
bool operator==(const Allocator<T>& l, const Allocator<T>& r)
{ return l.m_allocate == r.m_allocate; }
template<typename T>
bool operator!=(const Allocator<T>& l, const Allocator<T>& r)
{ return !(l == r); }
Allocator<int> a(custom_malloc, custom_free);
std::vector<int, Allocator<int>> v(a);
If you're using not using C++11 yet then you need to provide a lot more members for your allocator to meet the old requirements, but the one above is OK for C++11. Using custom allocators in C++03 is difficult and not portable anyway, so you should aim to use a C++11 compiler if you need to do this.
Upvotes: 5
Reputation: 1
Yes. As an example, look into header gc/gc_allocator.h
from Boehm garbage collector (you could easily replace the lower calls to GC_MALLOC
etc by some function pointers). See this answer.
Upvotes: 0
Reputation: 8087
Since allocators cannot be state-full but must be default constructible, I would suggest using templates to instantiate the allocators at compile time.
Upvotes: -2