Reputation: 26060
I need to write a function to retrieve and process some data. This data may be allocated in several ways (on the data segment, on the heap, on a shared memory segment and so on):
T *data;
if( global ) data = &d;
if( heap ) data = new T [ size ];
if( shm ) data = (T*) shmat( id, 0, 0 );
// processing data ...
Since data
may be dynamically allocated, I'd think that the best way to handle it is using an unique_ptr
or some other kind of smart pointers. However it's not always dynamically allocated: I'd need to choose at runtime the deleter for unique_ptr
, but that's not possible.
How should I define and handle data
?
Upvotes: 2
Views: 455
Reputation: 218710
In addition to KennyTm's good answer, another possibility is to use a function pointer as your deleter, and then supply different functions at run time:
typedef std::unique_ptr<T, void(*)(void*)> Ptr;
void delete_global(void*);
void delete_heap(void*);
// etc.
Ptr get(/* whatever */)
{
if ( ... )
return Ptr(data, delete_global);
if (... )
return Ptr(data, delete_heap);
// etc.
}
Upvotes: 3
Reputation: 523214
You could make the custom deleter take a run-time value!
struct MyCustomDeleter
{
MemoryType type;
template <typename T>
void operator()(T* value) const
{
switch (type)
{
case MemoryType::heap:
delete[] value;
break;
case MemoryType::shm:
unmap_from_shm(value);
break;
// etc.
}
}
};
...
std::unique_ptr<T, MyCustomDeleter> ptr (new T[size],
MyCustomDeleter{MemoryType::heap});
Upvotes: 6
Reputation: 229583
If you use a shared shared_ptr<>
you can choose the deleter at runtime. As long as you don't copy/... the shared_ptr
it should behave the same as a unique_ptr
.
Upvotes: 1
Reputation: 16256
I'm not sure about std::unique_ptr
, but you can use std::shared_ptr
. Its custom deleter doesn't depend on class template parameter.
Upvotes: 3
Reputation: 8421
Use your own smart pointer with a deleter you choose:
enum DataPointerType
{
Stack,
Dynamic,
SharedMem,
...
};
template <class T>
class DataPointer
{
public:
DataPointer(T* pointer, DataPointerType type)
: _ptr(pointer), _type(type)
{ }
~DataPointer()
{
switch (type) {
case Stack: break;
case Dynamic: delete _ptr; _ptr = nullptr; break;
...
}
}
T& operator*() { return *_ptr; }
const T& operator*() const { return *ptr; }
T* operator->() { return _ptr; }
const T* operator->() const { return ptr; }
private:
T* _ptr;
DataPointerType _type;
// Prevent copying and destruction, dangerous
DataPointer(const DataPointer& other);
DataPointer& operator=(const DataPointer& other);
};
Upvotes: 0