Commit d816ed88 authored by Stepan Palamarchuk's avatar Stepan Palamarchuk Committed by Anton Likhtarov

Introduce destruction callbacks

Summary:
This change allows users to track lifetime of EventBase and perform clean shutdown when EventBase gets destructed.

It is useful for users that rely on EventBase lifetime, but don't have any feedback mechanism with the owner of EventBase.

For instance some part of code might remain running in background on the EventBase after the main object was destroyed (e.g. it might be finalizing some async requests). In such case the original owner doesn't know that there's something still running and may try to destroy EventBase. In that case such background code will remain zombie forever.

AsyncMcClient changes are presented just as an example of usage.

@davejwatson, @simpkins: Could you please take a look at the proposed changes for the EventBase? If this is something not worth adding into EventBase, could you recommend a better way of doing things?

Test Plan: fbmake runtests

Reviewed By: alikhtarov@fb.com

Subscribers: folly@lists, simpkins, davejwatson

FB internal diff: D1353101
parent 3ed4f961
...@@ -178,6 +178,13 @@ EventBase::EventBase(event_base* evb) ...@@ -178,6 +178,13 @@ EventBase::EventBase(event_base* evb)
} }
EventBase::~EventBase() { 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 // 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 // (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 // its own data structures if it destroys the EventBase with unfired events
...@@ -445,6 +452,12 @@ void EventBase::runInLoop(Cob&& cob, bool thisIteration) { ...@@ -445,6 +452,12 @@ void EventBase::runInLoop(Cob&& cob, bool thisIteration) {
} }
} }
void EventBase::runOnDestruction(LoopCallback* callback) {
DCHECK(isInEventBaseThread());
callback->cancelLoopCallback();
onDestructionCallbacks_.push_back(*callback);
}
bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) { bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) {
// Send the message. // Send the message.
// It will be received by the FunctionRunner in the EventBase's thread. // It will be received by the FunctionRunner in the EventBase's thread.
......
...@@ -240,6 +240,18 @@ class EventBase : private boost::noncopyable, public TimeoutManager { ...@@ -240,6 +240,18 @@ class EventBase : private boost::noncopyable, public TimeoutManager {
void runInLoop(Cob&& c, bool thisIteration = false); void runInLoop(Cob&& c, bool thisIteration = false);
/**
* Adds the given callback to a queue of things run before destruction
* of current EventBase.
*
* This allows users of EventBase that run in it, but don't control it,
* to be notified before EventBase gets destructed.
*
* Note: will be called from the thread that invoked EventBase destructor,
* before the final run of loop callbacks.
*/
void runOnDestruction(LoopCallback* callback);
/** /**
* Run the specified function in the EventBase's thread. * Run the specified function in the EventBase's thread.
* *
...@@ -500,6 +512,7 @@ class EventBase : private boost::noncopyable, public TimeoutManager { ...@@ -500,6 +512,7 @@ class EventBase : private boost::noncopyable, public TimeoutManager {
CobTimeout::List pendingCobTimeouts_; CobTimeout::List pendingCobTimeouts_;
LoopCallbackList loopCallbacks_; LoopCallbackList loopCallbacks_;
LoopCallbackList onDestructionCallbacks_;
// This will be null most of the time, but point to currentCallbacks // This will be null most of the time, but point to currentCallbacks
// if we are in the middle of running loop callbacks, such that // if we are in the middle of running loop callbacks, such that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment