Summary: This is actually a bug, future.cancel() doesn't work with the current THreadWheelTimekeeper, because cancel() only works from the eventBase thread.
Test Plan: added unittest. Crashes before, passes now
Reviewed By: hans@fb.com
Subscribers: doug, folly-diffs@, jsedgwick, yfeldblum, chalfant
FB internal diff:
D2091531
Signature: t1:
2091531:
1432224024:
4aa5dd71de15b1344034a414d47c97ffaba68949
// Our Callback object for HHWheelTimer
struct WTCallback : public folly::HHWheelTimer::Callback {
// Only allow creation by this factory, to ensure heap allocation.
// Our Callback object for HHWheelTimer
struct WTCallback : public folly::HHWheelTimer::Callback {
// Only allow creation by this factory, to ensure heap allocation.
- static WTCallback* create() {
+ static WTCallback* create(EventBase* base) {
// optimization opportunity: memory pool
// optimization opportunity: memory pool
- return new WTCallback();
+ return new WTCallback(base);
}
Future<void> getFuture() {
}
Future<void> getFuture() {
- explicit WTCallback() {
+ explicit WTCallback(EventBase* base)
+ : base_(base) {
promise_.setInterruptHandler(
std::bind(&WTCallback::interruptHandler, this));
}
promise_.setInterruptHandler(
std::bind(&WTCallback::interruptHandler, this));
}
}
void interruptHandler() {
}
void interruptHandler() {
- cancelTimeout();
- delete this;
+ base_->runInEventBaseThread([=] {
+ cancelTimeout();
+ delete this;
+ });
}
Future<void> ThreadWheelTimekeeper::after(Duration dur) {
}
Future<void> ThreadWheelTimekeeper::after(Duration dur) {
- auto cob = WTCallback::create();
+ auto cob = WTCallback::create(&eventBase_);
auto f = cob->getFuture();
eventBase_.runInEventBaseThread([=]{
wheelTimer_->scheduleTimeout(cob, dur);
auto f = cob->getFuture();
eventBase_.runInEventBaseThread([=]{
wheelTimer_->scheduleTimeout(cob, dur);
std::chrono::milliseconds const one_ms(1);
std::chrono::milliseconds const awhile(10);
std::chrono::milliseconds const one_ms(1);
std::chrono::milliseconds const awhile(10);
+std::chrono::seconds const too_long(10);
std::chrono::steady_clock::time_point now() {
return std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point now() {
return std::chrono::steady_clock::now();
// just testing compilation here
}
// just testing compilation here
}
+TEST(Timekeeper, interruptDoesntCrash) {
+ auto f = futures::sleep(too_long);
+ f.cancel();
+}
+
// TODO(5921764)
/*
TEST(Timekeeper, onTimeoutPropagates) {
// TODO(5921764)
/*
TEST(Timekeeper, onTimeoutPropagates) {