/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 #include <functional> #include <memory> #include <queue> #include <thread> #include <type_traits> #include <typeindex> #include <unordered_set> #include <vector> #include <folly/AtomicIntrusiveLinkedList.h> #include <folly/CPortability.h> #include <folly/Executor.h> #include <folly/IntrusiveList.h> #include <folly/Likely.h> #include <folly/Portability.h> #include <folly/Try.h> #include <folly/functional/Invoke.h> #include <folly/io/async/HHWheelTimer.h> #include <folly/io/async/Request.h> #include <folly/executors/ExecutionObserver.h> #include <folly/fibers/BoostContextCompatibility.h> #include <folly/fibers/Fiber.h> #include <folly/fibers/GuardPageAllocator.h> #include <folly/fibers/LoopController.h> #include <folly/fibers/traits.h> namespace folly { template <class T> class Future; namespace fibers { class Baton; class Fiber; struct TaskOptions; template <typename T> class LocalType { … }; class InlineFunctionRunner { … }; /** * @class FiberManager * @brief Single-threaded task execution engine. * * FiberManager allows semi-parallel task execution on the same thread. Each * task can notify FiberManager that it is blocked on something (via await()) * call. This will pause execution of this task and it will be resumed only * when it is unblocked (via setData()). */ class FiberManager : public ::folly::Executor { … }; /** * @return true iff we are running in a fiber's context */ inline bool onFiber() { … } /** * Add a new task to be executed. * * @param func Task functor; must have a signature of `void func()`. * The object will be destroyed once task execution is complete. */ template <typename F> inline void addTask(F&& func) { … } template <typename F> inline void addTaskEager(F&& func) { … } /** * Add a new task. When the task is complete, execute finally(Try<Result>&&) * on the main context. * Task functor is run and destroyed on the fiber context. * Finally functor is run and destroyed on the main context. * * @param func Task functor; must have a signature of `T func()` for some T. * @param finally Finally functor; must have a signature of * `void finally(Try<T>&&)` and will be passed * the result of func() (including the exception if occurred). */ template <typename F, typename G> inline void addTaskFinally(F&& func, G&& finally) { … } template <typename F, typename G> inline void addTaskFinallyEager(F&& func, G&& finally) { … } /** * Blocks task execution until given promise is fulfilled. * * Calls function passing in a Promise<T>, which has to be fulfilled. * * @return data which was used to fulfill the promise. */ template <typename F> typename FirstArgOf<F>::type::value_type inline await_async(F&& func); #if !defined(_MSC_VER) template <typename F> FOLLY_ERASE typename FirstArgOf<F>::type::value_type await(F&& func) { … } #endif /** * If called from a fiber, immediately switches to the FiberManager's context * and runs func(), going back to the Fiber's context after completion. * Outside a fiber, just calls func() directly. * * @return value returned by func(). */ template <typename F> invoke_result_t<F> inline runInMainContext(F&& func); /** * Returns a refference to a fiber-local context for given Fiber. Should be * always called with the same T for each fiber. Fiber-local context is lazily * default-constructed on first request. * When new task is scheduled via addTask / addTaskRemote from a fiber its * fiber-local context is copied into the new fiber. */ template <typename T> T& local() { … } inline void yield() { … } } // namespace fibers } // namespace folly #include <folly/fibers/FiberManagerInternal-inl.h>