I have the following code that uses a C++ object of class Datum
within an Objective-C function work
:
void work(const Datum &datum) {
dispatch_async(dispatch_get_main_queue(), ^{
// Work with datum.
});
}
This code is called with an instance that is actually a boost::shared_ptr<Datum>
, i.e.
boost::shared_ptr<Datum> the_datum(new Datum());
work(*the_datum);
In this situation it is possible that the instance the_datum
gets deallocated before the block is run inside work
(the call to dispatch_async
performs an asynchronous operation on datum
that is executed later; the call and thus the function work
return immediately). This obviously results in a disaster.
One solution might be to not pass a reference to work
, but a boost::shared_ptr<Datum>
, instead. But there may be situations when references are preferred, see e.g. this thread. Is there any way to keep the interface of work
(i.e., pass datum
as a reference), but still prevent the deallocation of the shared pointer prior to the completion of the block?
There is no way to accomplish this by leaving the interface to work()
the same, and pass in a reference to datum
. There is no way to use the datum
to prevent the reference count from decrementing. Consider the following buggy program:
#include <memory>
int main () {
std::shared_ptr<int> p1(new int);
int &x = *p1;
std::shared_ptr<int> p2(&x);
}
This code crashes with a double free, because the shared_ptr<>
control structure does not follow the pointer to the object, but is followed through shared_ptr<>
itself.
What you can do is change work()
to take a shared_ptr()
, but add some more code to the block passed to dispatch_async()
so that it can use a reference within that code. Since you are transferring ownership to the asynchronous routine, you should use unique_ptr<>
instead. I know zilch about Objective-C, so this syntax might be wrong:
void work(std::unique_ptr<Datum> &datumptr_ref) {
__block std::unique_ptr<Datum> datumptr(std::move(datumptr_ref));
dispatch_async(dispatch_get_main_queue(), ^{
Datum &datum = *datumptr
// Work with datum.
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With