]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/seastar/src/core/future.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / src / core / future.cc
diff --git a/ceph/src/seastar/src/core/future.cc b/ceph/src/seastar/src/core/future.cc
new file mode 100644 (file)
index 0000000..614193b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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
+ */
+
+#include <seastar/core/future.hh>
+#include <seastar/core/reactor.hh>
+#include <seastar/core/report_exception.hh>
+#include <seastar/util/backtrace.hh>
+
+namespace seastar {
+namespace internal {
+
+promise_base::promise_base(promise_base&& x) noexcept
+    : _future(x._future), _state(x._state), _task(std::exchange(x._task, nullptr)) {
+    x._state = nullptr;
+    if (auto* fut = _future) {
+        fut->detach_promise();
+        fut->_promise = this;
+    }
+}
+
+promise_base::~promise_base() noexcept {
+    if (_future) {
+        assert(_state);
+        assert(_state->available() || !_task);
+        _future->detach_promise();
+    } else if (__builtin_expect(bool(_task), false)) {
+        assert(_state && !_state->available());
+        _state->set_to_broken_promise();
+        ::seastar::schedule(std::exchange(_task, nullptr));
+    }
+}
+
+template <promise_base::urgent Urgent>
+void promise_base::make_ready() noexcept {
+    if (_task) {
+        _state = nullptr;
+        if (Urgent == urgent::yes && !need_preempt()) {
+            ::seastar::schedule_urgent(std::exchange(_task, nullptr));
+        } else {
+            ::seastar::schedule(std::exchange(_task, nullptr));
+        }
+    }
+}
+
+template void promise_base::make_ready<promise_base::urgent::no>() noexcept;
+template void promise_base::make_ready<promise_base::urgent::yes>() noexcept;
+
+template
+future<> internal::current_exception_as_future() noexcept;
+}
+
+/**
+ * engine_exit() exits the reactor. It should be given a pointer to the
+ * exception which prompted this exit - or a null pointer if the exit
+ * request was not caused by any exception.
+ */
+void engine_exit(std::exception_ptr eptr) {
+    if (!eptr) {
+        engine().exit(0);
+        return;
+    }
+    report_exception("Exiting on unhandled exception", eptr);
+    engine().exit(1);
+}
+
+broken_promise::broken_promise() : logic_error("broken promise") { }
+
+future_state_base future_state_base::current_exception() {
+    return future_state_base(std::current_exception());
+}
+
+void future_state_base::set_to_broken_promise() noexcept {
+    try {
+        // Constructing broken_promise may throw (std::logic_error ctor is not noexcept).
+        set_exception(std::make_exception_ptr(broken_promise{}));
+    } catch (...) {
+        set_exception(std::current_exception());
+    }
+}
+
+void report_failed_future(const std::exception_ptr& eptr) noexcept {
+    ++engine()._abandoned_failed_futures;
+    seastar_logger.warn("Exceptional future ignored: {}, backtrace: {}", eptr, current_backtrace());
+}
+
+void report_failed_future(const future_state_base& state) noexcept {
+    report_failed_future(state._u.ex);
+}
+
+}