f4dd1ce876ed5395c053c56b58baa4eb3cbdd25f
[folly.git] / folly / fibers / BoostContextCompatibility.h
1 /*
2  * Copyright 2016 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/context/fcontext.hpp>
19 #include <boost/version.hpp>
20 #include <glog/logging.h>
21
22 /**
23  * Wrappers for different versions of boost::context library
24  * API reference for different versions
25  * Boost 1.51:
26  * http://www.boost.org/doc/libs/1_51_0/libs/context/doc/html/context/context/boost_fcontext.html
27  * Boost 1.52:
28  * http://www.boost.org/doc/libs/1_52_0/libs/context/doc/html/context/context/boost_fcontext.html
29  * Boost 1.56:
30  * http://www.boost.org/doc/libs/1_56_0/libs/context/doc/html/context/context/boost_fcontext.html
31  */
32
33 namespace folly {
34 namespace fibers {
35
36 class FiberImpl {
37 #if BOOST_VERSION >= 105600
38   using FiberContext = boost::context::fcontext_t;
39 #elif BOOST_VERSION >= 105200
40   using FiberContext = boost::context::fcontext_t*;
41 #else
42   using FiberContext = boost::ctx::fcontext_t;
43 #endif
44
45 #if BOOST_VERSION >= 105600
46   using MainContext = boost::context::fcontext_t;
47 #elif BOOST_VERSION >= 105200
48   using MainContext = boost::context::fcontext_t;
49 #else
50   using MainContext = boost::ctx::fcontext_t;
51 #endif
52
53  public:
54   FiberImpl(
55       folly::Function<void()> func,
56       unsigned char* stackLimit,
57       size_t stackSize)
58       : func_(std::move(func)) {
59     auto stackBase = stackLimit + stackSize;
60
61 #if BOOST_VERSION >= 105200
62     fiberContext_ =
63         boost::context::make_fcontext(stackBase, stackSize, &fiberFunc);
64 #else
65     fiberContext_.fc_stack.limit = stackLimit;
66     fiberContext_.fc_stack.base = stackBase;
67     make_fcontext(&fiberContext_, &fiberFunc);
68 #endif
69   }
70
71   void activate() {
72 #if BOOST_VERSION >= 105200
73     auto context = boost::context::jump_fcontext(
74         &mainContext_, fiberContext_, reinterpret_cast<intptr_t>(this));
75 #else
76     auto context = jump_fcontext(
77         &mainContext_, &fiberContext_, reinterpret_cast<intptr_t>(this));
78 #endif
79     DCHECK_EQ(0, context);
80   }
81
82   void deactivate() {
83 #if BOOST_VERSION >= 105600
84     auto context =
85         boost::context::jump_fcontext(&fiberContext_, mainContext_, 0);
86 #elif BOOST_VERSION >= 105200
87     auto context =
88         boost::context::jump_fcontext(fiberContext_, &mainContext_, 0);
89 #else
90     auto context = jump_fcontext(&fiberContext_, &mainContext_, 0);
91 #endif
92     DCHECK_EQ(this, reinterpret_cast<FiberImpl*>(context));
93   }
94
95  private:
96   static void fiberFunc(intptr_t arg) {
97     auto fiberImpl = reinterpret_cast<FiberImpl*>(arg);
98     fiberImpl->func_();
99   }
100
101   folly::Function<void()> func_;
102   FiberContext fiberContext_;
103   MainContext mainContext_;
104 };
105 }
106 } // folly::fibers