-
Notifications
You must be signed in to change notification settings - Fork 182
/
get_stop_token.hpp
93 lines (80 loc) · 2.99 KB
/
get_stop_token.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <unifex/blocking.hpp>
#include <unifex/coroutine.hpp>
#include <unifex/inplace_stop_token.hpp>
#include <unifex/stop_token_concepts.hpp>
#include <unifex/tag_invoke.hpp>
#include <unifex/type_traits.hpp>
#include <unifex/unstoppable_token.hpp>
#include <unifex/detail/unifex_fwd.hpp>
#include <unifex/detail/prologue.hpp>
namespace unifex {
namespace _get_stop_token {
inline const struct _fn {
#if !UNIFEX_NO_COROUTINES
private:
class _awaitable {
template <typename StopToken>
struct _awaiter {
StopToken stoken_;
bool await_ready() const noexcept { return true; }
void await_suspend(coro::coroutine_handle<>) const noexcept {}
StopToken await_resume() noexcept { return (StopToken &&) stoken_; }
// TODO: how do we express always-inline awaitables?
friend constexpr auto
tag_invoke(tag_t<unifex::blocking>, const _awaiter&) noexcept {
return blocking_kind::always_inline;
}
};
template(typename Tag, typename Promise) //
(requires same_as<
Tag,
tag_t<await_transform>>) //
friend auto tag_invoke(Tag, Promise& promise, _awaitable) noexcept {
return _awaiter<std::invoke_result_t<_fn, Promise&>>{_fn{}(promise)};
}
};
public:
// `co_await get_stop_token()` to fetch a coroutine's current stop token.
[[nodiscard]] constexpr _awaitable operator()() const noexcept { return {}; }
#endif
template(typename T) //
(requires(!tag_invocable<_fn, const T&>)) //
constexpr auto
operator()(const T&) const noexcept -> unstoppable_token {
return unstoppable_token{};
}
template(typename T) //
(requires tag_invocable<_fn, const T&>) //
constexpr auto
operator()(const T& object) const noexcept
-> tag_invoke_result_t<_fn, const T&> {
static_assert(
is_nothrow_tag_invocable_v<_fn, const T&>,
"get_stop_token() customisations must be declared noexcept");
return tag_invoke(_fn{}, object);
}
} get_stop_token{};
} // namespace _get_stop_token
using _get_stop_token::get_stop_token;
template <typename T>
using get_stop_token_result_t = std::invoke_result_t<tag_t<get_stop_token>, T>;
template <typename Receiver>
using stop_token_type_t = remove_cvref_t<get_stop_token_result_t<Receiver>>;
} // namespace unifex
#include <unifex/detail/epilogue.hpp>