Instrument fibers execution
authorAndre Pinto <aap@fb.com>
Thu, 16 Apr 2015 00:56:57 +0000 (17:56 -0700)
committerAlecs King <int@fb.com>
Mon, 27 Apr 2015 23:41:18 +0000 (16:41 -0700)
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

folly/Makefile.am
folly/experimental/fibers/ExecutionObserver.h [new file with mode: 0644]
folly/experimental/fibers/FiberManager-inl.h
folly/experimental/fibers/FiberManager.cpp
folly/experimental/fibers/FiberManager.h

index daa849b81f313e6e31c8aa6045ee8aaf19a8c397..ccc475ba81349c2978b597ac5ca3a5e488fe5643 100644 (file)
@@ -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 (file)
index 0000000..5cf1cc0
--- /dev/null
@@ -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
index e77ccb45c5912d94c2d559cfa5a3735af8efdaf9..793cf1fab534ad6dd78fa7583d1a386b675d330c 100644 (file)
@@ -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);
index 744478ab981ab955850cce31f7d0ac9455d7c53d..6ad7174dd91b81a90e14e1ca06910ef17678cd2b 100644 (file)
@@ -109,4 +109,8 @@ void FiberManager::remoteReadyInsert(Fiber* fiber) {
   }
 }
 
+void FiberManager::setObserver(ExecutionObserver* observer) {
+  observer_ = observer;
+}
+
 }}
index ee55cd6d57e33d6d1fe07c9b1f4e47069243615f..fa4e14aaf26068d7d7db518b889f3870a8db043c 100644 (file)
@@ -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_;