void VirtualEventBase::destroyImpl() { try { { // After destroyPromise_ is posted this object may be destroyed, so make // sure we release EventBase's keep-alive token before that. SCOPE_EXIT { evb_.reset(); }; clearCobTimeouts(); while (!onDestructionCallbacks_.rlock()->empty()) { // To avoid potential deadlock, do not hold the mutex while invoking // user-supplied callbacks. EventBase::OnDestructionCallback::List callbacks; onDestructionCallbacks_.swap(callbacks); while (!callbacks.empty()) { auto& callback = callbacks.front(); callbacks.pop_front(); callback.runCallback(); } } } destroyPromise_.set_value(); } catch (...) { destroyPromise_.set_exception(std::current_exception()); } }
void VirtualEventBase::destroyImpl() { // Make sure we release EventBase KeepAlive token even if exception occurs auto evbLoopKeepAlive = std::move(evbLoopKeepAlive_); try { clearCobTimeouts(); onDestructionCallbacks_.withWLock([&](LoopCallbackList& callbacks) { while (!callbacks.empty()) { auto& callback = callbacks.front(); callbacks.pop_front(); callback.runLoopCallback(); } }); destroyPromise_.set_value(); } catch (...) { destroyPromise_.set_exception(std::current_exception()); } }