Reputation: 5525
I am working with a 3rd party C API set in C++ that has two methods of concern for this discussion:
I have created a custom allocator wrapping the_api_malloc() and the_api_free() to use with for example std::vector. This works great.
What I'd like to do is have a std::vector type class that utilizes my custom allocator but also has a release() method that when called, releases ownership of it's memory and therefor will not call my custom allocators the_api_free().
pointer release() /* pointer is of T* */
Example usage:
MyClass myClass(1024); // the_api_malloc()'s 1024 bytes
// ... do something with myClass
the_api_give_back(myClass.release());
I'm not sure the best way to pull this off. What I have right now as a experiment is rather nasty:
class MyClass : public std::vector<char, MyAllocator<char> > {
public:
using typename std::vector<char, MyAllocator<char> >::pointer;
pointer release() {
// note: visual studio impl.
pointer p = this->_Myfirst;
this->_Myfirst = 0;
this->_Mylast = 0;
this->_Myend = 0;
return p;
}
}
Is there a better way?
UPDATE 1: Here is what I've tried based on suggestions below. This should also help illustrate desired behavior & where it is currently failing.
template <class T>
class MyAllocator
{
public:
// types omitted for clarity
MyAllocator() : m_released(false) { }
template <class U>
MyAllocator(MyAllocator<U> const& a) : m_released(a.m_released) { }
// other ctors, dtors, etc. omitted for clarity
// note: allocate() utilizes the_api_malloc()
void deallocate(pointer p, size_type num)
{
if(!m_released) {
the_api_free(p);
}
}
void release_ownership() { m_released = true; }
bool m_released;
};
template <typename T>
char* ReleaseOwernship(T& container)
{
container.get_allocator().release_ownership();
return &container[0];
}
// usage:
{ // scope
std::vector<char, MyAllocator<char> > vec;
// ...do something to populate vec...
char* p = ReleaseOwnership(vec);
the_api_give_back(p); // this API takes ownership of p and will delete it itself
} // end scope - note that MyAllocator::deallocate() gets called here -- m_release is still false
UPDATE 2: Tried creating a MyOwningAllocator and a MyNonOwningAllocator then swapping from the owning to the non-owning where at "release time", but can't get swap() to work as they are different types.
Upvotes: 2
Views: 3270
Reputation: 15207
I don't know if you were able to finish your implementation but I were able to code a solution for the same issue using modern C++ in this other SO answer.
Upvotes: 1
Reputation: 137810
vector::swap
will transfer ownership of the allocated block to another vector
. However, there is no way to stop a vector from calling vector::allocator_type::deallocate
in its destructor, and there is no portable way to directly modify the internal pointers.
Upvotes: 1
Reputation: 490148
Instead of trying to stop the vector from calling the allocator's free function, I'd include your release
as a member of your allocator, and have it set a flag. When the flag is set, the_api_free
will simply return (i.e., act as a nop).
Upvotes: 1