Let me start with background context.
Often time, in server side programming, our function call may go async (i.e. to shift the work to another thread in callback because of IO). So the pattern is function A calls B, B calls C and eventually in many layer deep down in function Z, we may decide to go async.
Function A needs to transfer ownership managed by a unique_ptr by using std::move
all the way to function Z. However, move unique_ptr
is 40 nsec (vs 20 nsec passing shared_ptr
by value or 1 nsec for passing raw pointer). For extremely perf sensitive server application, we may not want to do unique_ptr
move through so many layers of functions. For similar reasons, we don't want to use shared_ptr
(more importantly shared_ptr
always messes up ownership).
To be clear, we can use raw pointers and manage the resource ourselves. We always have that option and it could ultimately be the best option. But for the sake of argument, I think there is another option that I want to get people's opinion on.
So the proposed pattern is to pass raw pointer from the unique_ptr
all the way from function A to Z. At function Z where I need to go async, I create a new unique_ptr
based on the passed raw pointer and move to the new thread (i.e. I can capture the raw pointer in lambda, and create the new unique_ptr
in lambda's body and execute the lambda in new thread). At function A, if there is no exception thrown (i.e. the transfer succeeded), I will call release on unique_ptr
so there is no double release. If there is exception, then I will not call release so the caller in A will free the unique_ptr's resource. This way, I avoided a chain of move of unique_ptr and still be able to. See example below.
void Foo1(MyObj* po)
{
auto l =[po](){ auto u = std::unique_ptr<MyObj>(po); };
std::thread t(l);
t.join();
}
int main()
{
auto p1 = std::make_unique<MyObj>();
Foo1(p1.get());
std::cout<<"i am here\n";
p1.release();
}