]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright (C) 2019 ScyllaDB Ltd. | |
20 | */ | |
21 | ||
22 | #pragma once | |
23 | ||
f67539c2 TL |
24 | // Clang currently only supports the TS |
25 | #if __has_include(<coroutine>) && !defined(__clang__) | |
26 | #include <coroutine> | |
27 | #define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std | |
28 | #elif __has_include(<experimental/coroutine>) | |
9f95a23c | 29 | #include <experimental/coroutine> |
f67539c2 | 30 | #define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental |
9f95a23c | 31 | #else |
f67539c2 | 32 | #define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental |
9f95a23c TL |
33 | |
34 | // We are not exactly allowed to defined anything in the std namespace, but this | |
35 | // makes coroutines work with libstdc++. All of this is experimental anyway. | |
36 | ||
37 | namespace std::experimental { | |
38 | ||
20effc67 | 39 | template<typename Promise = void> |
9f95a23c TL |
40 | class coroutine_handle { |
41 | void* _pointer = nullptr; | |
42 | public: | |
43 | coroutine_handle() = default; | |
44 | ||
45 | coroutine_handle &operator=(nullptr_t) noexcept { | |
46 | _pointer = nullptr; | |
47 | return *this; | |
48 | } | |
49 | ||
50 | explicit operator bool() const noexcept { return _pointer; } | |
51 | ||
52 | static coroutine_handle from_address(void* ptr) noexcept { | |
53 | coroutine_handle hndl; | |
54 | hndl._pointer =ptr; | |
55 | return hndl; | |
56 | } | |
57 | void* address() const noexcept { return _pointer; } | |
58 | ||
59 | static coroutine_handle from_promise(Promise& promise) noexcept { | |
60 | coroutine_handle hndl; | |
61 | hndl._pointer = __builtin_coro_promise(&promise, alignof(Promise), true); | |
62 | return hndl; | |
63 | } | |
64 | Promise& promise() const noexcept { | |
65 | return *reinterpret_cast<Promise*>(__builtin_coro_promise(_pointer, alignof(Promise), false)); | |
66 | } | |
67 | ||
68 | void operator()() noexcept { resume(); } | |
69 | ||
70 | void resume() const noexcept { __builtin_coro_resume(_pointer); } | |
71 | void destroy() const noexcept { __builtin_coro_destroy(_pointer); } | |
72 | bool done() const noexcept { return __builtin_coro_done(_pointer); } | |
20effc67 TL |
73 | |
74 | operator coroutine_handle<>() const noexcept; | |
75 | }; | |
76 | ||
77 | template<> | |
78 | class coroutine_handle<void> { | |
79 | void* _pointer = nullptr; | |
80 | public: | |
81 | coroutine_handle() = default; | |
82 | ||
83 | coroutine_handle &operator=(nullptr_t) noexcept { | |
84 | _pointer = nullptr; | |
85 | return *this; | |
86 | } | |
87 | ||
88 | explicit operator bool() const noexcept { return _pointer; } | |
89 | ||
90 | static coroutine_handle from_address(void* ptr) noexcept { | |
91 | coroutine_handle hndl; | |
92 | hndl._pointer = ptr; | |
93 | return hndl; | |
94 | } | |
95 | void* address() const noexcept { return _pointer; } | |
96 | ||
97 | void operator()() noexcept { resume(); } | |
98 | ||
99 | void resume() const noexcept { __builtin_coro_resume(_pointer); } | |
100 | void destroy() const noexcept { __builtin_coro_destroy(_pointer); } | |
101 | bool done() const noexcept { return __builtin_coro_done(_pointer); } | |
9f95a23c TL |
102 | }; |
103 | ||
104 | struct suspend_never { | |
105 | constexpr bool await_ready() const noexcept { return true; } | |
106 | template<typename T> | |
107 | constexpr void await_suspend(coroutine_handle<T>) noexcept { } | |
108 | constexpr void await_resume() noexcept { } | |
109 | }; | |
110 | ||
111 | struct suspend_always { | |
112 | constexpr bool await_ready() const noexcept { return false; } | |
113 | template<typename T> | |
114 | constexpr void await_suspend(coroutine_handle<T>) noexcept { } | |
115 | constexpr void await_resume() noexcept { } | |
116 | }; | |
117 | ||
20effc67 TL |
118 | template <typename Promise> |
119 | coroutine_handle<Promise>::operator coroutine_handle<>() const noexcept { | |
120 | return coroutine_handle<>::from_address(address()); | |
121 | } | |
122 | ||
9f95a23c TL |
123 | template<typename T, typename... Args> |
124 | class coroutine_traits { }; | |
125 | ||
126 | } | |
127 | ||
128 | #endif |