In my application, I need to set callbacks whose sole responsibility is to update the state associated with a completed event in a separate object so that it can be queried later. However, because of how the API is designed, I can't guarantee that the other object will still be owned by the time the event completes, so I need to store a pointer to that object, and because the callback API is C-based, I end up storing a raw pointer to a smart pointer, and it's the ugliest piece of code I've seen*.
* Well in the last few hours anyways...
So this is what I wrote to accomplish this:
event.setCallback(CL_COMPLETE, [](cl_event event, cl_int, void* ptr) {
auto ptr_ptr = static_cast<std::weak_ptr<render_future::shared_state>*>(ptr);
if(auto shared_ptr = ptr_ptr->lock()) {
auto & shared_state = *shared_ptr;
std::lock_guard lock{ shared_state.mutex };
shared_state.event_state[event] = true;
}
delete ptr_ptr;
}, new std::weak_ptr<render_future::shared_state>(future.state));
In particular I object to my own use of new std::weak_ptr<render_future::shared_state>(future.state), which to me seems like some kind of antipattern: using naked new and delete in conjunction with smart pointers.
The problem, however, is that because the callback has to be a function pointer, my lambda expression cannot copy or reference other objects, and the only way to get the shared_state object inside the lambda is to pass its pointer in; and again, because I cannot guarantee that its lifetime hasn't expired, I need to take it in the form of a pointer to a weak_ptr so that it can be manipulated if (and only if) the object still exists.
So ultimately, my question is: is there an ideomatic way to pass shared_state into this callback where
- I can check to make sure the object still exists, while
- Also eliminating my use of naked
newanddeletecalls?