Some time ago I was looking for a way to invoke std::async
without the need of storing std::future
, thus not blocking the execution at the end of the scope. I found this answer which uses a captured std::shared_ptr
for an std::future
, therefore allowing to make a nonblocking call to std::async
.
Another way of deferring a destructor invocation is to prevent it from to be called at all. This can be achieved with in-place construction with operator new
.
Consider this version that uses a static thread local storage for an in-place constructed std::future<void>
:
template <class F>
void call_async(F&& fun) {
thread_local uint8_t buf[sizeof(std::future<void>)] = {0};
auto fut = new(buf) std::future<void>();
*fut = std::async(std::launch::async, [fun]() {
fun();
});
}
This version will not produce any heap-allocation related overhead, but it seems very illegal, though I am not sure why in particular.
I am aware that it is UB to use an object before it has been constructed, which is not the case. I am not sure why not calling delete
in this case would resolve in UB (for heap allocation it is not UB).
Possible problems that I see:
- calling a constructor on one object multiple times
- race condition when modifying the state (inner
std::promise
I suppose)
UPDATE
Constructing an object in the static storage directly (as has mentioned IlCapitano in the comments) will block each time a move assignment is called (shared state will be destroyed blocking the thread which has removed last reference to it).
Not calling a destructor will case a leak because of not released references to the shared state.