}
EventBase::~EventBase() {
+ // Keep looping until all keep-alive handles are released. Each keep-alive
+ // handle signals that some external code will still schedule some work on
+ // this EventBase (so it's not safe to destroy it).
+ while (!loopKeepAlive_.unique()) {
+ applyLoopKeepAlive();
+ loopOnce();
+ }
+
// Call all destruction callbacks, before we start cleaning up our state.
while (!onDestructionCallbacks_.empty()) {
LoopCallback* callback = &onDestructionCallbacks_.front();
std::thread t([&, loopKeepAlive = evb.loopKeepAlive() ] {
/* sleep override */ std::this_thread::sleep_for(
std::chrono::milliseconds(100));
- evb.runInEventBaseThread([&] { done = true; });
+ evb.runInEventBaseThread(
+ [&done, loopKeepAlive = std::move(loopKeepAlive) ] { done = true; });
});
evb.loop();
t = std::thread([&, loopKeepAlive = evb.loopKeepAlive() ] {
/* sleep override */ std::this_thread::sleep_for(
std::chrono::milliseconds(100));
- evb.runInEventBaseThread([&] { done = true; });
+ evb.runInEventBaseThread(
+ [&done, loopKeepAlive = std::move(loopKeepAlive) ] { done = true; });
});
});
t.join();
}
+
+TEST(EventBaseTest, LoopKeepAliveShutdown) {
+ auto evb = folly::make_unique<EventBase>();
+
+ bool done = false;
+
+ std::thread t(
+ [&done, loopKeepAlive = evb->loopKeepAlive(), evbPtr = evb.get() ] {
+ /* sleep override */ std::this_thread::sleep_for(
+ std::chrono::milliseconds(100));
+ evbPtr->runInEventBaseThread(
+ [&done, loopKeepAlive = std::move(loopKeepAlive) ] {
+ done = true;
+ });
+ });
+
+ evb.reset();
+
+ ASSERT_TRUE(done);
+
+ t.join();
+}