Fix folly::fibers on OSX with boost 1.60
[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
21 /**
22  * Wrappers for different versions of boost::context library
23  * API reference for different versions
24  * Boost 1.51:
25  * http://www.boost.org/doc/libs/1_51_0/libs/context/doc/html/context/context/boost_fcontext.html
26  * Boost 1.52:
27  * http://www.boost.org/doc/libs/1_52_0/libs/context/doc/html/context/context/boost_fcontext.html
28  * Boost 1.56:
29  * http://www.boost.org/doc/libs/1_56_0/libs/context/doc/html/context/context/boost_fcontext.html
30  */
31
32 namespace folly {
33 namespace fibers {
34
35 struct FContext {
36  public:
37 #if BOOST_VERSION >= 105200
38   using ContextStruct = boost::context::fcontext_t;
39 #else
40   using ContextStruct = boost::ctx::fcontext_t;
41 #endif
42
43   void* stackLimit() const {
44     return stackLimit_;
45   }
46
47   void* stackBase() const {
48     return stackBase_;
49   }
50
51  private:
52   void* stackLimit_;
53   void* stackBase_;
54
55 #if BOOST_VERSION >= 105600
56   ContextStruct context_;
57 #elif BOOST_VERSION >= 105200
58   ContextStruct* context_;
59 #else
60   ContextStruct context_;
61 #endif
62
63   friend intptr_t
64   jumpContext(FContext* oldC, FContext::ContextStruct* newC, intptr_t p);
65   friend intptr_t
66   jumpContext(FContext::ContextStruct* oldC, FContext* newC, intptr_t p);
67   friend FContext
68   makeContext(void* stackLimit, size_t stackSize, void (*fn)(intptr_t));
69 };
70
71 inline intptr_t
72 jumpContext(FContext* oldC, FContext::ContextStruct* newC, intptr_t p) {
73 #if BOOST_VERSION >= 105600
74   return boost::context::jump_fcontext(&oldC->context_, *newC, p);
75 #elif BOOST_VERSION >= 105200
76   return boost::context::jump_fcontext(oldC->context_, newC, p);
77 #else
78   return jump_fcontext(&oldC->context_, newC, p);
79 #endif
80 }
81
82 inline intptr_t
83 jumpContext(FContext::ContextStruct* oldC, FContext* newC, intptr_t p) {
84 #if BOOST_VERSION >= 105200
85   return boost::context::jump_fcontext(oldC, newC->context_, p);
86 #else
87   return jump_fcontext(oldC, &newC->context_, p);
88 #endif
89 }
90
91 inline FContext
92 makeContext(void* stackLimit, size_t stackSize, void (*fn)(intptr_t)) {
93   FContext res;
94   res.stackLimit_ = stackLimit;
95   res.stackBase_ = static_cast<unsigned char*>(stackLimit) + stackSize;
96
97 #if BOOST_VERSION >= 105200
98   res.context_ = boost::context::make_fcontext(res.stackBase_, stackSize, fn);
99 #else
100   res.context_.fc_stack.limit = stackLimit;
101   res.context_.fc_stack.base = res.stackBase_;
102   make_fcontext(&res.context_, fn);
103 #endif
104
105   return res;
106 }
107 }
108 } // folly::fibers