Seastar
High performance C++ framework for concurrent servers
do_with.hh
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) 2015 Cloudius Systems, Ltd.
20 */
21
22#pragma once
23
24#ifndef SEASTAR_MODULE
25#include <seastar/core/future.hh>
26#include <seastar/util/modules.hh>
27#include <utility>
28#include <memory>
29#include <tuple>
30#endif
31
32namespace seastar {
33
34
36
37namespace internal {
38
39template <typename HeldState, typename Future>
40class do_with_state final : public continuation_base_from_future<Future>::type {
41 HeldState _held;
42 typename Future::promise_type _pr;
43public:
44 template<typename... T>
45 explicit do_with_state(T&&... args) : _held(std::forward<T>(args)...) {}
46 virtual void run_and_dispose() noexcept override {
47 _pr.set_urgent_state(std::move(this->_state));
48 delete this;
49 }
50 task* waiting_task() noexcept override {
51 return _pr.waiting_task();
52 }
53 HeldState& data() {
54 return _held;
55 }
56 Future get_future() {
57 return _pr.get_future();
58 }
59};
60
61}
63
64namespace internal {
65template <typename Tuple, size_t... Idx>
66inline
67auto
68cherry_pick_tuple(std::index_sequence<Idx...>, Tuple&& tuple) {
69 return std::forward_as_tuple(std::get<Idx>(std::forward<Tuple>(tuple))...);
70}
71
72template <typename Tuple, typename Seq>
73struct subtuple;
74
75template <typename Tuple, size_t... Idx>
76struct subtuple<Tuple, std::index_sequence<Idx...>> {
77 using type = std::tuple<std::decay_t<std::tuple_element_t<Idx, Tuple>>...>;
78};
79
80template <typename T1, typename T2, typename... More>
81inline
82auto
83do_with_impl(T1&& rv1, T2&& rv2, More&&... more) {
84 auto all = std::forward_as_tuple(
85 std::forward<T1>(rv1),
86 std::forward<T2>(rv2),
87 std::forward<More>(more)...);
88 constexpr size_t nr = std::tuple_size<decltype(all)>::value - 1;
89 using idx = std::make_index_sequence<nr>;
90 auto&& just_values = cherry_pick_tuple(idx(), std::move(all));
91 auto&& just_func = std::move(std::get<nr>(std::move(all)));
92 using value_tuple = typename subtuple<decltype(all), idx>::type;
93 using ret_type = decltype(std::apply(just_func, std::declval<value_tuple&>()));
94 auto task = std::apply(
95 [](auto&&... x) {
96 return std::make_unique<internal::do_with_state<value_tuple, ret_type>>(std::forward<decltype(x)>(x)...);
97 },
98 std::move(just_values));
99 auto fut = std::apply(just_func, task->data());
100 if (fut.available()) {
101 return fut;
102 }
103 auto ret = task->get_future();
104 internal::set_callback(std::move(fut), task.release());
105 return ret;
106}
107}
108
109
110SEASTAR_MODULE_EXPORT_BEGIN
111
114
132template <typename T1, typename T2, typename... More>
133inline
134auto
135do_with(T1&& rv1, T2&& rv2, More&&... more) noexcept {
136 auto func = internal::do_with_impl<T1, T2, More...>;
137 return futurize_invoke(func, std::forward<T1>(rv1), std::forward<T2>(rv2), std::forward<More>(more)...);
138}
139
147template<typename Lock, typename Func>
148inline
149auto with_lock(Lock& lock, Func&& func) {
150 return lock.lock().then([&lock, func = std::forward<Func>(func)] () mutable {
151 return futurize_invoke(func).finally([&lock] {
152 lock.unlock();
153 });
154 });
155}
156
158
159SEASTAR_MODULE_EXPORT_END
160
161}
auto do_with(T1 &&rv1, T2 &&rv2, More &&... more) noexcept
Definition: do_with.hh:135
auto with_lock(Lock &lock, Func &&func)
Definition: do_with.hh:149
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
STL namespace.