From 3d381a3571e4c773a498ddc5216a52875bd86ae6 Mon Sep 17 00:00:00 2001 From: Brian Watling Date: Tue, 19 May 2015 08:30:03 -0700 Subject: [PATCH] Add 'runnable' callback to ExecutionObserver Summary: Add a callback when a fiber becomes runnable Test Plan: unit tests Reviewed By: andrii@fb.com Subscribers: alikhtarov, folly-diffs@, yfeldblum, chalfant FB internal diff: D2081306 Signature: t1:2081306:1432011152:0ee93cb2682eb2a289b99c403e91465e72dd4ee8 --- folly/experimental/fibers/ExecutionObserver.h | 17 ++++++++++++-- folly/experimental/fibers/Fiber.cpp | 4 ++++ folly/experimental/fibers/FiberManager-inl.h | 22 +++++++++++++++---- folly/experimental/fibers/FiberManager.cpp | 3 +++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/folly/experimental/fibers/ExecutionObserver.h b/folly/experimental/fibers/ExecutionObserver.h index 5cf1cc00..ef5f8fb0 100644 --- a/folly/experimental/fibers/ExecutionObserver.h +++ b/folly/experimental/fibers/ExecutionObserver.h @@ -15,6 +15,8 @@ */ #pragma once +#include + namespace folly { namespace fibers { /** @@ -26,13 +28,24 @@ class ExecutionObserver { /** * Called when a task is about to start executing. + * + * @param id Unique id for the fiber which is starting. + */ + virtual void starting(uintptr_t id) noexcept = 0; + + /** + * Called when a task is ready to run. + * + * @param id Unique id for the fiber which is ready to run. */ - virtual void starting() noexcept = 0; + virtual void runnable(uintptr_t id) noexcept = 0; /** * Called just after a task stops executing. + * + * @param id Unique id for the fiber which is stopping. */ - virtual void stopped() noexcept = 0; + virtual void stopped(uintptr_t id) noexcept = 0; }; }} // namespace folly::fibers diff --git a/folly/experimental/fibers/Fiber.cpp b/folly/experimental/fibers/Fiber.cpp index 40e94641..2a562774 100644 --- a/folly/experimental/fibers/Fiber.cpp +++ b/folly/experimental/fibers/Fiber.cpp @@ -60,6 +60,10 @@ void Fiber::setData(intptr_t data) { data_ = data; state_ = READY_TO_RUN; + if (fiberManager_.observer_) { + fiberManager_.observer_->runnable(reinterpret_cast(this)); + } + if (LIKELY(threadId_ == localThreadId())) { fiberManager_.readyFibers_.push_back(*this); fiberManager_.ensureLoopScheduled(); diff --git a/folly/experimental/fibers/FiberManager-inl.h b/folly/experimental/fibers/FiberManager-inl.h index 97df9cab..c0f0d557 100644 --- a/folly/experimental/fibers/FiberManager-inl.h +++ b/folly/experimental/fibers/FiberManager-inl.h @@ -64,7 +64,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { fiber->state_ == Fiber::READY_TO_RUN); currentFiber_ = fiber; if (observer_) { - observer_->starting(); + observer_->starting(reinterpret_cast(fiber)); } while (fiber->state_ == Fiber::NOT_STARTED || @@ -86,7 +86,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { awaitFunc_(*fiber); awaitFunc_ = nullptr; if (observer_) { - observer_->stopped(); + observer_->stopped(reinterpret_cast(fiber)); } currentFiber_ = nullptr; } else if (fiber->state_ == Fiber::INVALID) { @@ -107,7 +107,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { } // Make sure LocalData is not accessible from its destructor if (observer_) { - observer_->stopped(); + observer_->stopped(reinterpret_cast(fiber)); } currentFiber_ = nullptr; fiber->localData_.reset(); @@ -122,7 +122,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { } } else if (fiber->state_ == Fiber::YIELDED) { if (observer_) { - observer_->stopped(); + observer_->stopped(reinterpret_cast(fiber)); } currentFiber_ = nullptr; fiber->state_ = Fiber::READY_TO_RUN; @@ -168,12 +168,20 @@ inline bool FiberManager::loopUntilNoReady() { fiber->setFunction(std::move(task->func)); fiber->data_ = reinterpret_cast(fiber); + if (observer_) { + observer_->runnable(reinterpret_cast(fiber)); + } runReadyFiber(fiber); hadRemoteFiber = true; } ); } + if (observer_) { + for (auto& yielded : yieldedFibers_) { + observer_->runnable(reinterpret_cast(&yielded)); + } + } readyFibers_.splice(readyFibers_.end(), yieldedFibers_); return fibersActive_ > 0; @@ -233,6 +241,9 @@ void FiberManager::addTask(F&& func) { fiber->data_ = reinterpret_cast(fiber); readyFibers_.push_back(*fiber); + if (observer_) { + observer_->runnable(reinterpret_cast(fiber)); + } ensureLoopScheduled(); } @@ -364,6 +375,9 @@ void FiberManager::addTaskFinally(F&& func, G&& finally) { fiber->data_ = reinterpret_cast(fiber); readyFibers_.push_back(*fiber); + if (observer_) { + observer_->runnable(reinterpret_cast(fiber)); + } ensureLoopScheduled(); } diff --git a/folly/experimental/fibers/FiberManager.cpp b/folly/experimental/fibers/FiberManager.cpp index 6ad7174d..445b65ad 100644 --- a/folly/experimental/fibers/FiberManager.cpp +++ b/folly/experimental/fibers/FiberManager.cpp @@ -104,6 +104,9 @@ size_t FiberManager::stackHighWatermark() const { } void FiberManager::remoteReadyInsert(Fiber* fiber) { + if (observer_) { + observer_->runnable(reinterpret_cast(fiber)); + } if (remoteReadyQueue_.insertHead(fiber)) { loopController_->scheduleThreadSafe(); } -- 2.34.1