bool EventBase::runLoopCallbacks(bool setContext) { if (!loopCallbacks_.empty()) { bumpHandlingTime(); // Swap the loopCallbacks_ list with a temporary list on our stack. // This way we will only run callbacks scheduled at the time // runLoopCallbacks() was invoked. // // If any of these callbacks in turn call runInLoop() to schedule more // callbacks, those new callbacks won't be run until the next iteration // around the event loop. This prevents runInLoop() callbacks from being // able to start file descriptor and timeout based events. LoopCallbackList currentCallbacks; currentCallbacks.swap(loopCallbacks_); runOnceCallbacks_ = ¤tCallbacks; while (!currentCallbacks.empty()) { LoopCallback* callback = ¤tCallbacks.front(); currentCallbacks.pop_front(); if (setContext) { RequestContext::setContext(callback->context_); } callback->runLoopCallback(); } runOnceCallbacks_ = nullptr; return true; } return false; }
EventBase::~EventBase() { // Call all destruction callbacks, before we start cleaning up our state. while (!onDestructionCallbacks_.empty()) { LoopCallback* callback = &onDestructionCallbacks_.front(); onDestructionCallbacks_.pop_front(); callback->runLoopCallback(); } // Delete any unfired CobTimeout objects, so that we don't leak memory // (Note that we don't fire them. The caller is responsible for cleaning up // its own data structures if it destroys the EventBase with unfired events // remaining.) while (!pendingCobTimeouts_.empty()) { CobTimeout* timeout = &pendingCobTimeouts_.front(); delete timeout; } (void) runLoopCallbacks(false); // Stop consumer before deleting NotificationQueue fnRunner_->stopConsuming(); event_base_free(evb_); VLOG(5) << "EventBase(): Destroyed."; }