Several of my objects contain unique_ptr
instances as members and specify a move-constructor:
struct Foo {
Foo(Foo&& other): someA(std::move(other.someA)), someB(other.someB){}
unique_ptr<A> someA;
B someB;
}
This means I can move Foo
objects around, but not copy them. And whenever they go out of scope, the default destructor will invoke the destructor of the unique_ptr
instances:
void someFunc(Foo&& foo);
{
Foo a;
Foo b;
someFunc(Foo()); // compiles
someFunc(std::move(a)); // compiles -> a.someA is now nullptr
someFunc(b); // does not compile, because copy is not allowed
} // <- b is destructed and object guarded by b.someA is deleted
Now, I want to move such an object into a container and later obtain it again. This is no problem for C++ containers, because they can handle move semantics. Unfortunately my container is provided by a C-based real time OS (FreeRTOS Queue: https://www.freertos.org/xQueueSendToBack.html). Its access functions xQueueSendToBack
and xQueueReceive
obtain void*
pointing to the item in order to use memcpy
or an equivalent to move items in and out of the container.
My (simplified) solution for a wrapper of the Queue looks like this:
template <typename T, std::size_t N>
struct FreeRtosQueue {
bool sendToBack(T&& item) {
if (xQueueSendToBack(this->frtosQueueHandle, &item, portMAX_DELAY) != pdTRUE) {
return false;
}
return true;
} // <- item destructor called without prior move
T receive() {
T item;
xQueueReceive(this->frtosQueueHandle, &item, portMAX_DELAY);
return item;
}
QueueHandle_t frtosQueueHandle;
};
Unfortunately, at the end of sendToBack
the destructor of the item will be called, without having it moved (from the C++ perspective). This results in all objects guarded by unique_ptr
s within the item being deleted.
- How can I prevent the destruction of moveable objects within the queued item?
- Do you see any problems with the
receive
implementation?