Move mcrouter/lib/fibers to folly/experimental/fibers
[folly.git] / folly / experimental / fibers / Fiber.h
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17
18 #include <functional>
19
20 #include <boost/context/all.hpp>
21 #include <boost/version.hpp>
22 #include <folly/AtomicLinkedList.h>
23 #include <folly/IntrusiveList.h>
24 #include <folly/experimental/fibers/BoostContextCompatibility.h>
25
26 namespace folly { namespace fibers {
27
28 class Baton;
29 class FiberManager;
30
31 /**
32  * @class Fiber
33  * @brief Fiber object used by FiberManager to execute tasks.
34  *
35  * Each Fiber object can be executing at most one task at a time. In active
36  * phase it is running the task function and keeps its context.
37  * Fiber is also used to pass data to blocked task and thus unblock it.
38  * Each Fiber may be associated with a single FiberManager.
39  */
40 class Fiber {
41  public:
42   /**
43    * Sets data for the blocked task
44    *
45    * @param data this data will be returned by await() when task is resumed.
46    */
47   void setData(intptr_t data);
48
49   Fiber(const Fiber&) = delete;
50   Fiber& operator=(const Fiber&) = delete;
51
52   ~Fiber();
53  private:
54   enum State {
55     INVALID,                    /**< Does't have task function */
56     NOT_STARTED,                /**< Has task function, not started */
57     READY_TO_RUN,               /**< Was started, blocked, then unblocked */
58     RUNNING,                    /**< Is running right now */
59     AWAITING,                   /**< Is currently blocked */
60     AWAITING_IMMEDIATE,         /**< Was preempted to run an immediate function,
61                                      and will be resumed right away */
62   };
63
64   State state_{INVALID};        /**< current Fiber state */
65
66   friend class Baton;
67   friend class FiberManager;
68
69   explicit Fiber(FiberManager& fiberManager);
70
71   template <typename F>
72   void setFunction(F&& func);
73
74   template <typename F, typename G>
75   void setFunctionFinally(F&& func, G&& finally);
76
77   template <typename G>
78   void setReadyFunction(G&& func);
79
80   static void fiberFuncHelper(intptr_t fiber);
81   void fiberFunc();
82
83   /**
84    * Switch out of fiber context into the main context,
85    * performing necessary housekeeping for the new state.
86    *
87    * @param state New state, must not be RUNNING.
88    *
89    * @return The value passed back from the main context.
90    */
91   intptr_t preempt(State state);
92
93   /**
94    * Examines how much of the stack we used at this moment and
95    * registers with the FiberManager (for monitoring).
96    */
97   void recordStackPosition();
98
99   FiberManager& fiberManager_;  /**< Associated FiberManager */
100   FContext fcontext_;           /**< current task execution context */
101   intptr_t data_;               /**< Used to keep some data with the Fiber */
102   std::function<void()> func_;  /**< task function */
103   std::function<void()> readyFunc_; /**< function to be executed before jumping
104                                          to this fiber */
105
106   /**
107    * Points to next fiber in remote ready list
108    */
109   folly::AtomicLinkedListHook<Fiber> nextRemoteReady_;
110
111   static constexpr size_t kUserBufferSize = 256;
112   std::aligned_storage<kUserBufferSize>::type userBuffer_;
113
114   void* getUserBuffer();
115
116   std::function<void()> resultFunc_;
117   std::function<void()> finallyFunc_;
118
119   folly::IntrusiveListHook listHook_; /**< list hook for different FiberManager
120                                            queues */
121   pid_t threadId_{0};
122 };
123
124 }}
125
126 #include <folly/experimental/fibers/Fiber-inl.h>