Skip to content

Commit

Permalink
Schedule libev loop immediately when an event was scheduled with this…
Browse files Browse the repository at this point in the history
…Iteration=false

Reviewed By: mjoras

Differential Revision: D61225298

fbshipit-source-id: 8d00facc1f34a5aab1657c843d43fb2c2cb47d2d
  • Loading branch information
kvtsoy authored and facebook-github-bot committed Aug 14, 2024
1 parent a260a1b commit 50d641d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 0 deletions.
22 changes: 22 additions & 0 deletions quic/common/events/LibevQuicEventBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ void libEvPrepareCallback(
CHECK(self != nullptr);
self->checkCallbacks();
}

void libEvAsyncCallback(
struct ev_loop* /* loop */,
ev_async* w,
int /* revents */) {
auto self = static_cast<quic::LibevQuicEventBase*>(w->data);
CHECK(self != nullptr);
self->checkCallbacks();
}

} // namespace

namespace quic {
Expand All @@ -37,10 +47,15 @@ LibevQuicEventBase::LibevQuicEventBase(struct ev_loop* loop) : ev_loop_(loop) {
ev_prepare_init(&prepareWatcher_, libEvPrepareCallback);
prepareWatcher_.data = this;
ev_prepare_start(ev_loop_, &prepareWatcher_);

ev_async_init(&asyncWatcher_, libEvAsyncCallback);
asyncWatcher_.data = this;
ev_async_start(ev_loop_, &asyncWatcher_);
}

LibevQuicEventBase::~LibevQuicEventBase() {
ev_prepare_stop(ev_loop_, &prepareWatcher_);
ev_async_stop(ev_loop_, &asyncWatcher_);

struct FunctionLoopCallbackDisposer {
void operator()(FunctionLoopCallback* callback) {
Expand Down Expand Up @@ -143,6 +158,13 @@ void LibevQuicEventBase::checkCallbacks() {
currentLoopWrappers.front().runLoopCallback();
}
runOnceCallbackWrappers_ = nullptr;

if (wakeUpImmediatelyOnPendingScheduledEvents_ &&
!loopCallbackWrappers_.empty()) {
// We have newly added events for the next loop. Wake up as soon as
// possible.
ev_async_send(ev_loop_, &asyncWatcher_);
}
}

bool LibevQuicEventBase::isInEventBaseThread() const {
Expand Down
6 changes: 6 additions & 0 deletions quic/common/events/LibevQuicEventBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ class LibevQuicEventBase
return std::chrono::milliseconds(1);
}

void wakeUpImmediatelyOnPendingScheduledEvents() override {
wakeUpImmediatelyOnPendingScheduledEvents_ = true;
}

struct ev_loop* getLibevLoop() {
return ev_loop_;
}
Expand Down Expand Up @@ -223,5 +227,7 @@ class LibevQuicEventBase
// We're using it to execute delayed work given to us via runInLoop.
ev_prepare prepareWatcher_;
std::atomic<std::thread::id> loopThreadId_;
bool wakeUpImmediatelyOnPendingScheduledEvents_{false};
ev_async asyncWatcher_;
};
} // namespace quic
2 changes: 2 additions & 0 deletions quic/common/events/QuicEventBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ class QuicEventBase {

virtual void terminateLoopSoon() = 0;

virtual void wakeUpImmediatelyOnPendingScheduledEvents() {}

[[nodiscard]] virtual std::chrono::milliseconds getTimerTickInterval()
const = 0;

Expand Down
1 change: 1 addition & 0 deletions quic/common/events/test/QuicEventBaseMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class QuicEventBaseMock : public QuicEventBase {
MOCK_METHOD((bool), loopIgnoreKeepAlive, ());
MOCK_METHOD((void), terminateLoopSoon, ());
MOCK_METHOD((std::chrono::milliseconds), getTimerTickInterval, (), (const));
MOCK_METHOD((void), wakeUpImmediatelyOnPendingScheduledEvents, ());
};

} // namespace quic::test

0 comments on commit 50d641d

Please sign in to comment.