Use Fiber locals for TAO Fiber-locals
[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 #include <typeinfo>
20
21 #include <boost/context/all.hpp>
22 #include <boost/version.hpp>
23 #include <folly/AtomicLinkedList.h>
24 #include <folly/IntrusiveList.h>
25 #include <folly/experimental/fibers/BoostContextCompatibility.h>
26
27 namespace folly { namespace fibers {
28
29 class Baton;
30 class FiberManager;
31
32 /**
33  * @class Fiber
34  * @brief Fiber object used by FiberManager to execute tasks.
35  *
36  * Each Fiber object can be executing at most one task at a time. In active
37  * phase it is running the task function and keeps its context.
38  * Fiber is also used to pass data to blocked task and thus unblock it.
39  * Each Fiber may be associated with a single FiberManager.
40  */
41 class Fiber {
42  public:
43   /**
44    * Sets data for the blocked task
45    *
46    * @param data this data will be returned by await() when task is resumed.
47    */
48   void setData(intptr_t data);
49
50   Fiber(const Fiber&) = delete;
51   Fiber& operator=(const Fiber&) = delete;
52
53   ~Fiber();
54  private:
55   enum State {
56     INVALID,                    /**< Does't have task function */
57     NOT_STARTED,                /**< Has task function, not started */
58     READY_TO_RUN,               /**< Was started, blocked, then unblocked */
59     RUNNING,                    /**< Is running right now */
60     AWAITING,                   /**< Is currently blocked */
61     AWAITING_IMMEDIATE,         /**< Was preempted to run an immediate function,
62                                      and will be resumed right away */
63   };
64
65   State state_{INVALID};        /**< current Fiber state */
66
67   friend class Baton;
68   friend class FiberManager;
69
70   explicit Fiber(FiberManager& fiberManager);
71
72   template <typename F>
73   void setFunction(F&& func);
74
75   template <typename F, typename G>
76   void setFunctionFinally(F&& func, G&& finally);
77
78   static void fiberFuncHelper(intptr_t fiber);
79   void fiberFunc();
80
81   /**
82    * Switch out of fiber context into the main context,
83    * performing necessary housekeeping for the new state.
84    *
85    * @param state New state, must not be RUNNING.
86    *
87    * @return The value passed back from the main context.
88    */
89   intptr_t preempt(State state);
90
91   /**
92    * Examines how much of the stack we used at this moment and
93    * registers with the FiberManager (for monitoring).
94    */
95   void recordStackPosition();
96
97   FiberManager& fiberManager_;  /**< Associated FiberManager */
98   FContext fcontext_;           /**< current task execution context */
99   intptr_t data_;               /**< Used to keep some data with the Fiber */
100   std::function<void()> func_;  /**< task function */
101
102   /**
103    * Points to next fiber in remote ready list
104    */
105   folly::AtomicLinkedListHook<Fiber> nextRemoteReady_;
106
107   static constexpr size_t kUserBufferSize = 256;
108   std::aligned_storage<kUserBufferSize>::type userBuffer_;
109
110   void* getUserBuffer();
111
112   std::function<void()> resultFunc_;
113   std::function<void()> finallyFunc_;
114
115   class LocalData {
116    public:
117     LocalData() {}
118     LocalData(const LocalData& other);
119     LocalData& operator=(const LocalData& other);
120
121     template <typename T>
122     T& get();
123
124     void reset();
125
126     //private:
127     static void* allocateHeapBuffer(size_t size);
128     static void freeHeapBuffer(void* buffer);
129
130     template <typename T>
131     static void dataCopyConstructor(void*, const void*);
132     template <typename T>
133     static void dataBufferDestructor(void*);
134     template <typename T>
135     static void dataHeapDestructor(void*);
136
137     static constexpr size_t kBufferSize = 128;
138     std::aligned_storage<kBufferSize>::type buffer_;
139     size_t dataSize_;
140
141     const std::type_info* dataType_;
142     void (*dataDestructor_)(void*);
143     void (*dataCopyConstructor_)(void*, const void*);
144     void* data_{nullptr};
145   };
146
147   LocalData localData_;
148
149   folly::IntrusiveListHook listHook_; /**< list hook for different FiberManager
150                                            queues */
151   pid_t threadId_{0};
152 };
153
154 }}
155
156 #include <folly/experimental/fibers/Fiber-inl.h>