From: Andre Pinto <aap@fb.com>
Date: Thu, 16 Apr 2015 00:56:57 +0000 (-0700)
Subject: Instrument fibers execution
X-Git-Tag: v0.36.0~37
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=fa78ffbcc6956fbbc9ff95fbab27070ef6cfc6e2;p=folly.git

Instrument fibers execution

Summary: Add option to setup fibers' instrumentation.

Test Plan: Unit tests

Reviewed By: andrii@fb.com

Subscribers: folly-diffs@, yfeldblum, chalfant

FB internal diff: D1991638

Tasks: 6347990

Signature: t1:1991638:1429144487:3c3586b9943b4cc6bbef0297e48b8bffaf586f0d
---

diff --git a/folly/Makefile.am b/folly/Makefile.am
index daa849b8..ccc475ba 100644
--- a/folly/Makefile.am
+++ b/folly/Makefile.am
@@ -80,6 +80,7 @@ nobase_follyinclude_HEADERS = \
 	experimental/fibers/BoostContextCompatibility.h \
 	experimental/fibers/EventBaseLoopController.h \
 	experimental/fibers/EventBaseLoopController-inl.h \
+	experimental/fibers/ExecutionObserver.h \
 	experimental/fibers/Fiber.h \
 	experimental/fibers/Fiber-inl.h \
 	experimental/fibers/FiberManager.h \
diff --git a/folly/experimental/fibers/ExecutionObserver.h b/folly/experimental/fibers/ExecutionObserver.h
new file mode 100644
index 00000000..5cf1cc00
--- /dev/null
+++ b/folly/experimental/fibers/ExecutionObserver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+namespace folly { namespace fibers {
+
+/**
+ * Observes the execution of a task.
+ */
+class ExecutionObserver {
+ public:
+  virtual ~ExecutionObserver() { }
+
+  /**
+   * Called when a task is about to start executing.
+   */
+  virtual void starting() noexcept = 0;
+
+  /**
+   * Called just after a task stops executing.
+   */
+  virtual void stopped() noexcept = 0;
+};
+
+}} // namespace folly::fibers
diff --git a/folly/experimental/fibers/FiberManager-inl.h b/folly/experimental/fibers/FiberManager-inl.h
index e77ccb45..793cf1fa 100644
--- a/folly/experimental/fibers/FiberManager-inl.h
+++ b/folly/experimental/fibers/FiberManager-inl.h
@@ -47,6 +47,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
   assert(fiber->state_ == Fiber::NOT_STARTED ||
          fiber->state_ == Fiber::READY_TO_RUN);
   currentFiber_ = fiber;
+  if (observer_) {
+    observer_->starting();
+  }
 
   while (fiber->state_ == Fiber::NOT_STARTED ||
          fiber->state_ == Fiber::READY_TO_RUN) {
@@ -66,6 +69,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
   if (fiber->state_ == Fiber::AWAITING) {
     awaitFunc_(*fiber);
     awaitFunc_ = nullptr;
+    if (observer_) {
+      observer_->stopped();
+    }
     currentFiber_ = nullptr;
   } else if (fiber->state_ == Fiber::INVALID) {
     assert(fibersActive_ > 0);
@@ -84,6 +90,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
       fiber->finallyFunc_ = nullptr;
     }
     // Make sure LocalData is not accessible from its destructor
+    if (observer_) {
+      observer_->stopped();
+    }
     currentFiber_ = nullptr;
     fiber->localData_.reset();
 
@@ -96,6 +105,9 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
       --fibersAllocated_;
     }
   } else if (fiber->state_ == Fiber::YIELDED) {
+    if (observer_) {
+      observer_->stopped();
+    }
     currentFiber_ = nullptr;
     fiber->state_ = Fiber::READY_TO_RUN;
     yieldedFibers_.push_back(*fiber);
diff --git a/folly/experimental/fibers/FiberManager.cpp b/folly/experimental/fibers/FiberManager.cpp
index 744478ab..6ad7174d 100644
--- a/folly/experimental/fibers/FiberManager.cpp
+++ b/folly/experimental/fibers/FiberManager.cpp
@@ -109,4 +109,8 @@ void FiberManager::remoteReadyInsert(Fiber* fiber) {
   }
 }
 
+void FiberManager::setObserver(ExecutionObserver* observer) {
+  observer_ = observer;
+}
+
 }}
diff --git a/folly/experimental/fibers/FiberManager.h b/folly/experimental/fibers/FiberManager.h
index ee55cd6d..fa4e14aa 100644
--- a/folly/experimental/fibers/FiberManager.h
+++ b/folly/experimental/fibers/FiberManager.h
@@ -29,6 +29,7 @@
 #include <folly/futures/Try.h>
 
 #include <folly/experimental/fibers/BoostContextCompatibility.h>
+#include <folly/experimental/fibers/ExecutionObserver.h>
 #include <folly/experimental/fibers/Fiber.h>
 #include <folly/experimental/fibers/traits.h>
 
@@ -234,6 +235,14 @@ class FiberManager {
    */
   void yield();
 
+  /**
+   * Setup fibers execution observation/instrumentation. Fiber locals are
+   * available to observer.
+   *
+   * @param observer  Fiber's execution observer.
+   */
+  void setObserver(ExecutionObserver* observer);
+
   static FiberManager& getFiberManager();
   static FiberManager* getFiberManagerUnsafe();
 
@@ -349,6 +358,11 @@ class FiberManager {
    */
   std::function<void()> immediateFunc_;
 
+  /**
+   * Fiber's execution observer.
+   */
+  ExecutionObserver* observer_{nullptr};
+
   ExceptionCallback exceptionCallback_; /**< task exception callback */
 
   folly::AtomicLinkedList<Fiber, &Fiber::nextRemoteReady_> remoteReadyQueue_;