+ //
+ // Even shared_ptr of cob is captured in lambda this is still somewhat *racy*
+ // because it will be released once timeout is scheduled. So technically there
+ // is no gurantee that EventBase thread can safely call timeout callback.
+ // However due to fact that we are having circular reference here:
+ // WTCallback->Promise->Core->WTCallbak, so three of them won't go away until
+ // we break the circular reference. The break happens either in
+ // WTCallback::timeoutExpired or WTCallback::interruptHandler. Former means
+ // timeout callback is being safely executed. Latter captures shared_ptr of
+ // WTCallback again in another lambda for canceling timeout. The moment
+ // canceling timeout is executed in EventBase thread, the actual timeout
+ // callback has either been executed, or will never be executed. So we are
+ // fine here.
+ //
+ if (!eventBase_.runInEventBaseThread([this, cob, dur]{
+ wheelTimer_->scheduleTimeout(cob.get(), dur);
+ })) {
+ // Release promise to break the circular reference. Because if
+ // scheduleTimeout fails, there is nothing to *promise*. Internally
+ // Core would automatically set an exception result when Promise is
+ // destructed before fulfilling.
+ // This is either called from EventBase thread, or here.
+ // They are somewhat racy but given the rare chance this could fail,
+ // I don't see it is introducing any problem yet.
+ cob->releasePromise();
+ }