From 8aceb9bf727c42de013dd3fff8c89bd5d75ff11b Mon Sep 17 00:00:00 2001 From: Giorgi Papakerashvili Date: Fri, 15 Mar 2024 20:23:42 -0700 Subject: [PATCH] Define callback types for folly::ExecutionObserver Summary: For folly::ExecutionObserver we want to know what type of callback are we dealing with. Currently introducing 4 different types of callbacks: 1. LibeventCallbacks - Those are the ones inside EventHandler::libeventCallback 2. LoopCallbacks - Those are user defined callbacks, classes derived from LoopCallback and implementing `runLoopCallback` method 3. NotificationQueueCallbacks - Anytime someones does `runInEventBaseThread` from different thread we put this on notification queue and then execute them as a batch 4. Fiber callbacks - Not sure if we really needs this? Reviewed By: ot Differential Revision: D54395157 fbshipit-source-id: fe79adf5986f9e8dc79f93fae9f39c457d9961b2 --- folly/experimental/ExecutionObserver.h | 12 ++++++++++-- folly/fibers/FiberManagerInternal-inl.h | 16 ++++++++++++---- folly/io/async/EventBase.cpp | 22 ++++++++++++++++------ folly/io/async/EventHandler.cpp | 8 ++++++-- folly/io/async/test/EventBaseTestLib.h | 10 ++++++++-- 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/folly/experimental/ExecutionObserver.h b/folly/experimental/ExecutionObserver.h index 310baa03655..f837f6d3f2f 100644 --- a/folly/experimental/ExecutionObserver.h +++ b/folly/experimental/ExecutionObserver.h @@ -31,6 +31,14 @@ class ExecutionObserver : public boost::intrusive::list_base_hook< boost::intrusive::link_mode> { public: + enum class CallbackType { + // Owned by EventBase. + Event, + Loop, + NotificationQueue, + // Owned by FiberManager. + Fiber, + }; // Constant time size = false to support auto_unlink behavior, options are // mutually exclusive typedef boost::intrusive:: @@ -44,14 +52,14 @@ class ExecutionObserver * * @param id Unique id for the task which is starting. */ - virtual void starting(uintptr_t id) noexcept = 0; + virtual void starting(uintptr_t id, CallbackType callbackType) noexcept = 0; /** * Called just after a task stops executing. * * @param id Unique id for the task which stopped. */ - virtual void stopped(uintptr_t id) noexcept = 0; + virtual void stopped(uintptr_t id, CallbackType callbackType) noexcept = 0; }; } // namespace folly diff --git a/folly/fibers/FiberManagerInternal-inl.h b/folly/fibers/FiberManagerInternal-inl.h index 5297241d5e2..c12f4c73f7f 100644 --- a/folly/fibers/FiberManagerInternal-inl.h +++ b/folly/fibers/FiberManagerInternal-inl.h @@ -138,7 +138,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { if (!observerList_.empty()) { for (auto& observer : observerList_) { - observer.starting(reinterpret_cast(fiber)); + observer.starting( + reinterpret_cast(fiber), + folly::ExecutionObserver::CallbackType::Fiber); } } @@ -160,7 +162,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { awaitFunc_(*fiber); awaitFunc_ = nullptr; for (auto& observer : observerList_) { - observer.stopped(reinterpret_cast(fiber)); + observer.stopped( + reinterpret_cast(fiber), + folly::ExecutionObserver::CallbackType::Fiber); } currentFiber_ = nullptr; fiber->rcontext_ = RequestContext::saveContext(); @@ -184,7 +188,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { } // Make sure LocalData is not accessible from its destructor for (auto& observer : observerList_) { - observer.stopped(reinterpret_cast(fiber)); + observer.stopped( + reinterpret_cast(fiber), + folly::ExecutionObserver::CallbackType::Fiber); } currentFiber_ = nullptr; @@ -209,7 +215,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { } } else if (fiber->state_ == Fiber::YIELDED) { for (auto& observer : observerList_) { - observer.stopped(reinterpret_cast(fiber)); + observer.stopped( + reinterpret_cast(fiber), + folly::ExecutionObserver::CallbackType::Fiber); } currentFiber_ = nullptr; fiber->rcontext_ = RequestContext::saveContext(); diff --git a/folly/io/async/EventBase.cpp b/folly/io/async/EventBase.cpp index f162de1dc9e..0163f557f1d 100644 --- a/folly/io/async/EventBase.cpp +++ b/folly/io/async/EventBase.cpp @@ -157,11 +157,15 @@ EventBaseBackend::~EventBaseBackend() { class ExecutionObserverScopeGuard { public: ExecutionObserverScopeGuard( - folly::ExecutionObserver::List* observerList, void* id) - : observerList_(observerList), id_{reinterpret_cast(id)} { + folly::ExecutionObserver::List* observerList, + void* id, + folly::ExecutionObserver::CallbackType callbackType) + : observerList_(observerList), + id_{reinterpret_cast(id)}, + callbackType_(callbackType) { if (!observerList_->empty()) { for (auto& observer : *observerList_) { - observer.starting(id_); + observer.starting(id_, callbackType_); } } } @@ -169,7 +173,7 @@ class ExecutionObserverScopeGuard { ~ExecutionObserverScopeGuard() { if (!observerList_->empty()) { for (auto& observer : *observerList_) { - observer.stopped(id_); + observer.stopped(id_, callbackType_); } } } @@ -177,6 +181,7 @@ class ExecutionObserverScopeGuard { private: folly::ExecutionObserver::List* observerList_; uintptr_t id_; + folly::ExecutionObserver::CallbackType callbackType_; }; } // namespace @@ -187,7 +192,9 @@ class EventBase::FuncRunner { explicit FuncRunner(EventBase& eventBase) : eventBase_(eventBase) {} void operator()(Func&& func) noexcept { ExecutionObserverScopeGuard guard( - &eventBase_.getExecutionObserverList(), &func); + &eventBase_.getExecutionObserverList(), + &func, + folly::ExecutionObserver::CallbackType::NotificationQueue); std::exchange(func, {})(); } @@ -924,7 +931,10 @@ void EventBase::runLoopCallbacks(LoopCallbackList& currentCallbacks) { LoopCallback* callback = ¤tCallbacks.front(); currentCallbacks.pop_front(); folly::RequestContextScopeGuard rctx(std::move(callback->context_)); - ExecutionObserverScopeGuard guard(&executionObserverList_, callback); + ExecutionObserverScopeGuard guard( + &executionObserverList_, + callback, + folly::ExecutionObserver::CallbackType::Loop); callback->runLoopCallback(); } } diff --git a/folly/io/async/EventHandler.cpp b/folly/io/async/EventHandler.cpp index 180d498b37b..35df02ef005 100644 --- a/folly/io/async/EventHandler.cpp +++ b/folly/io/async/EventHandler.cpp @@ -151,7 +151,9 @@ void EventHandler::libeventCallback(libevent_fd_t fd, short events, void* arg) { auto& observers = handler->eventBase_->getExecutionObserverList(); if (!observers.empty()) { for (auto& observer : observers) { - observer.starting(reinterpret_cast(handler)); + observer.starting( + reinterpret_cast(handler), + folly::ExecutionObserver::CallbackType::Event); } } @@ -162,7 +164,9 @@ void EventHandler::libeventCallback(libevent_fd_t fd, short events, void* arg) { if (!observers.empty()) { for (auto& observer : observers) { - observer.stopped(reinterpret_cast(handler)); + observer.stopped( + reinterpret_cast(handler), + folly::ExecutionObserver::CallbackType::Event); } } } diff --git a/folly/io/async/test/EventBaseTestLib.h b/folly/io/async/test/EventBaseTestLib.h index 76195e755ac..be0ae168cc7 100644 --- a/folly/io/async/test/EventBaseTestLib.h +++ b/folly/io/async/test/EventBaseTestLib.h @@ -163,13 +163,19 @@ FOLLY_ALWAYS_INLINE void scheduleEvents( class TestObserver : public folly::ExecutionObserver { public: - virtual void starting(uintptr_t /* id */) noexcept override { + virtual void starting( + uintptr_t /* id */, + folly::ExecutionObserver::CallbackType /* callbackType */) noexcept + override { if (nestedStart_ == 0) { nestedStart_ = 1; } numStartingCalled_++; } - virtual void stopped(uintptr_t /* id */) noexcept override { + virtual void stopped( + uintptr_t /* id */, + folly::ExecutionObserver::CallbackType /* callbackType */) noexcept + override { nestedStart_--; numStoppedCalled_++; }