summaryrefslogtreecommitdiffstats
path: root/src/seastar/include/seastar/core/with_timeout.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/seastar/include/seastar/core/with_timeout.hh73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/seastar/include/seastar/core/with_timeout.hh b/src/seastar/include/seastar/core/with_timeout.hh
new file mode 100644
index 000000000..cbe4758dd
--- /dev/null
+++ b/src/seastar/include/seastar/core/with_timeout.hh
@@ -0,0 +1,73 @@
+/*
+ * This file is open source software, licensed to you under the terms
+ * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. You may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2020 ScyllaDB.
+ */
+
+
+#pragma once
+
+#include <chrono>
+
+#include <seastar/core/future.hh>
+#include <seastar/core/timed_out_error.hh>
+#include <seastar/core/timer.hh>
+
+namespace seastar {
+
+/// \addtogroup future-util
+/// @{
+
+/// \brief Wait for either a future, or a timeout, whichever comes first
+///
+/// When timeout is reached the returned future resolves with an exception
+/// produced by ExceptionFactory::timeout(). By default it is \ref timed_out_error exception.
+///
+/// Note that timing out doesn't cancel any tasks associated with the original future.
+/// It also doesn't cancel the callback registerred on it.
+///
+/// \param f future to wait for
+/// \param timeout time point after which the returned future should be failed
+///
+/// \return a future which will be either resolved with f or a timeout exception
+template<typename ExceptionFactory = default_timeout_exception_factory, typename Clock, typename Duration, typename... T>
+future<T...> with_timeout(std::chrono::time_point<Clock, Duration> timeout, future<T...> f) {
+ if (f.available()) {
+ return f;
+ }
+ auto pr = std::make_unique<promise<T...>>();
+ auto result = pr->get_future();
+ timer<Clock> timer([&pr = *pr] {
+ pr.set_exception(std::make_exception_ptr(ExceptionFactory::timeout()));
+ });
+ timer.arm(timeout);
+ // Future is returned indirectly.
+ (void)f.then_wrapped([pr = std::move(pr), timer = std::move(timer)] (auto&& f) mutable {
+ if (timer.cancel()) {
+ f.forward_to(std::move(*pr));
+ } else {
+ f.ignore_ready_future();
+ }
+ });
+ return result;
+}
+
+/// @}
+
+} // namespace seastar