Fix copyright lines
[folly.git] / folly / fibers / BoostContextCompatibility.h
1 /*
2  * Copyright 2014-present 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 <boost/version.hpp>
19 #if BOOST_VERSION >= 106100
20 #include <boost/context/detail/fcontext.hpp>
21 #else
22 #include <boost/context/fcontext.hpp>
23 #endif
24 #include <glog/logging.h>
25
26 /**
27  * Wrappers for different versions of boost::context library
28  * API reference for different versions
29  * Boost 1.51:
30  * http://www.boost.org/doc/libs/1_51_0/libs/context/doc/html/context/context/boost_fcontext.html
31  * Boost 1.52:
32  * http://www.boost.org/doc/libs/1_52_0/libs/context/doc/html/context/context/boost_fcontext.html
33  * Boost 1.56:
34  * http://www.boost.org/doc/libs/1_56_0/libs/context/doc/html/context/context/boost_fcontext.html
35  * Boost 1.61:
36  * https://github.com/boostorg/context/blob/boost-1.61.0/include/boost/context/detail/fcontext.hpp
37  */
38
39 namespace folly {
40 namespace fibers {
41
42 class FiberImpl {
43 #if BOOST_VERSION >= 106100
44   using FiberContext = boost::context::detail::fcontext_t;
45 #elif BOOST_VERSION >= 105600
46   using FiberContext = boost::context::fcontext_t;
47 #elif BOOST_VERSION >= 105200
48   using FiberContext = boost::context::fcontext_t*;
49 #else
50   using FiberContext = boost::ctx::fcontext_t;
51 #endif
52
53 #if BOOST_VERSION >= 106100
54   using MainContext = boost::context::detail::fcontext_t;
55 #elif BOOST_VERSION >= 105600
56   using MainContext = boost::context::fcontext_t;
57 #elif BOOST_VERSION >= 105200
58   using MainContext = boost::context::fcontext_t;
59 #else
60   using MainContext = boost::ctx::fcontext_t;
61 #endif
62
63  public:
64   FiberImpl(
65       folly::Function<void()> func,
66       unsigned char* stackLimit,
67       size_t stackSize)
68       : func_(std::move(func)) {
69     auto stackBase = stackLimit + stackSize;
70 #if BOOST_VERSION >= 106100
71     fiberContext_ =
72         boost::context::detail::make_fcontext(stackBase, stackSize, &fiberFunc);
73 #elif BOOST_VERSION >= 105200
74     fiberContext_ =
75         boost::context::make_fcontext(stackBase, stackSize, &fiberFunc);
76 #else
77     fiberContext_.fc_stack.limit = stackLimit;
78     fiberContext_.fc_stack.base = stackBase;
79     make_fcontext(&fiberContext_, &fiberFunc);
80 #endif
81   }
82
83   void activate() {
84 #if BOOST_VERSION >= 106100
85     auto transfer = boost::context::detail::jump_fcontext(fiberContext_, this);
86     fiberContext_ = transfer.fctx;
87     auto context = reinterpret_cast<intptr_t>(transfer.data);
88 #elif BOOST_VERSION >= 105200
89     auto context = boost::context::jump_fcontext(
90         &mainContext_, fiberContext_, reinterpret_cast<intptr_t>(this));
91 #else
92     auto context = jump_fcontext(
93         &mainContext_, &fiberContext_, reinterpret_cast<intptr_t>(this));
94 #endif
95     DCHECK_EQ(0, context);
96   }
97
98   void deactivate() {
99 #if BOOST_VERSION >= 106100
100     auto transfer =
101         boost::context::detail::jump_fcontext(mainContext_, nullptr);
102     mainContext_ = transfer.fctx;
103     auto context = reinterpret_cast<intptr_t>(transfer.data);
104 #elif BOOST_VERSION >= 105600
105     auto context =
106         boost::context::jump_fcontext(&fiberContext_, mainContext_, 0);
107 #elif BOOST_VERSION >= 105200
108     auto context =
109         boost::context::jump_fcontext(fiberContext_, &mainContext_, 0);
110 #else
111     auto context = jump_fcontext(&fiberContext_, &mainContext_, 0);
112 #endif
113     DCHECK_EQ(this, reinterpret_cast<FiberImpl*>(context));
114   }
115
116  private:
117 #if BOOST_VERSION >= 106100
118   static void fiberFunc(boost::context::detail::transfer_t transfer) {
119     auto fiberImpl = reinterpret_cast<FiberImpl*>(transfer.data);
120     fiberImpl->mainContext_ = transfer.fctx;
121     fiberImpl->func_();
122   }
123 #else
124   static void fiberFunc(intptr_t arg) {
125     auto fiberImpl = reinterpret_cast<FiberImpl*>(arg);
126     fiberImpl->func_();
127   }
128 #endif
129
130   folly::Function<void()> func_;
131   FiberContext fiberContext_;
132   MainContext mainContext_;
133 };
134 } // namespace fibers
135 } // namespace folly