-void EventBase::loopForever() {
- // Update the notification queue event to treat it as a normal (non-internal)
- // event. The notification queue event always remains installed, and the main
- // loop won't exit with it installed.
- fnRunner_->stopConsuming();
- fnRunner_->startConsuming(this, queue_.get());
-
- bool ret = loop();
+ssize_t EventBase::loopKeepAliveCount() {
+ if (loopKeepAliveCountAtomic_.load(std::memory_order_relaxed)) {
+ loopKeepAliveCount_ +=
+ loopKeepAliveCountAtomic_.exchange(0, std::memory_order_relaxed);
+ }
+ DCHECK_GE(loopKeepAliveCount_, 0);
+ return loopKeepAliveCount_;
+}
+
+void EventBase::applyLoopKeepAlive() {
+ if (loopKeepAliveActive_ && loopKeepAliveCount() == 0) {
+ // Restore the notification queue internal flag
+ fnRunner_->stopConsuming();
+ fnRunner_->startConsumingInternal(this, queue_.get());
+ loopKeepAliveActive_ = false;
+ } else if (!loopKeepAliveActive_ && loopKeepAliveCount() > 0) {
+ // Update the notification queue event to treat it as a normal
+ // (non-internal) event. The notification queue event always remains
+ // installed, and the main loop won't exit with it installed.
+ fnRunner_->stopConsuming();
+ fnRunner_->startConsuming(this, queue_.get());
+ loopKeepAliveActive_ = true;
+ }
+}