]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/seastar/include/seastar/core/semaphore.hh
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / include / seastar / core / semaphore.hh
index 19ade46d53eb26c4474f450edb6d7f61680c661e..3725182f31b0ade57577772b10f5172f7e3ab518 100644 (file)
@@ -68,6 +68,36 @@ struct semaphore_default_exception_factory {
     }
 };
 
+class named_semaphore_timed_out : public semaphore_timed_out {
+    sstring _msg;
+public:
+    named_semaphore_timed_out(compat::string_view msg);
+    virtual const char* what() const noexcept {
+        return _msg.c_str();
+    }
+};
+
+class broken_named_semaphore : public broken_semaphore {
+    sstring _msg;
+public:
+    broken_named_semaphore(compat::string_view msg);
+    virtual const char* what() const noexcept {
+        return _msg.c_str();
+    }
+};
+
+// A factory of semaphore exceptions that contain additional context: the semaphore name
+// auto sem = named_semaphore(0, named_semaphore_exception_factory{"file_opening_limit_semaphore"});
+struct named_semaphore_exception_factory {
+    sstring name;
+    named_semaphore_timed_out timeout() {
+        return named_semaphore_timed_out(name);
+    }
+    broken_named_semaphore broken() {
+        return broken_named_semaphore(name);
+    }
+};
+
 /// \brief Counted resource guard.
 ///
 /// This is a standard computer science semaphore, adapted
@@ -83,15 +113,16 @@ struct semaphore_default_exception_factory {
 /// as a cancellation point.
 ///
 /// \tparam ExceptionFactory template parameter allows modifying a semaphore to throw
-/// customized exceptions on timeout/broken(). It has to provide two static functions
+/// customized exceptions on timeout/broken(). It has to provide two functions
 /// ExceptionFactory::timeout() and ExceptionFactory::broken() which return corresponding
 /// exception object.
 template<typename ExceptionFactory, typename Clock = typename timer<>::clock>
-class basic_semaphore {
+class basic_semaphore : private ExceptionFactory {
 public:
     using duration = typename timer<Clock>::duration;
     using clock = typename timer<Clock>::clock;
     using time_point = typename timer<Clock>::time_point;
+    using exception_factory = ExceptionFactory;
 private:
     ssize_t _count;
     std::exception_ptr _ex;
@@ -100,9 +131,11 @@ private:
         size_t nr;
         entry(promise<>&& pr_, size_t nr_) : pr(std::move(pr_)), nr(nr_) {}
     };
-    struct expiry_handler {
+    struct expiry_handler : public exception_factory {
+        expiry_handler() = default;
+        expiry_handler(exception_factory&& f) : exception_factory(std::move(f)) { }
         void operator()(entry& e) noexcept {
-            e.pr.set_exception(ExceptionFactory::timeout());
+            e.pr.set_exception(exception_factory::timeout());
         }
     };
     expiring_fifo<entry, expiry_handler, clock> _wait_list;
@@ -124,6 +157,7 @@ public:
     ///
     /// \param count number of initial units present in the counter.
     basic_semaphore(size_t count) : _count(count) {}
+    basic_semaphore(size_t count, exception_factory&& factory) : exception_factory(factory), _count(count), _wait_list(expiry_handler(std::move(factory))) {}
     /// Waits until at least a specific number of units are available in the
     /// counter, and reduces the counter by that amount of units.
     ///
@@ -251,7 +285,7 @@ public:
     /// Signal to waiters that an error occurred.  \ref wait() will see
     /// an exceptional future<> containing a \ref broken_semaphore exception.
     /// The future is made available immediately.
-    void broken() { broken(std::make_exception_ptr(ExceptionFactory::broken())); }
+    void broken() { broken(std::make_exception_ptr(exception_factory::broken())); }
 
     /// Signal to waiters that an error occurred.  \ref wait() will see
     /// an exceptional future<> containing the provided exception parameter.
@@ -399,11 +433,11 @@ get_units(basic_semaphore<ExceptionFactory, Clock>& sem, size_t units, typename
 ///      \ref seaphore_units object is alive.
 ///
 /// \related semaphore
-template<typename ExceptionFactory>
-future<semaphore_units<ExceptionFactory>>
-get_units(basic_semaphore<ExceptionFactory>& sem, size_t units, typename basic_semaphore<ExceptionFactory>::duration timeout) {
+template<typename ExceptionFactory, typename Clock>
+future<semaphore_units<ExceptionFactory, Clock>>
+get_units(basic_semaphore<ExceptionFactory, Clock>& sem, size_t units, typename basic_semaphore<ExceptionFactory, Clock>::duration timeout) {
     return sem.wait(timeout, units).then([&sem, units] {
-        return semaphore_units<ExceptionFactory>{ sem, units };
+        return semaphore_units<ExceptionFactory, Clock>{ sem, units };
     });
 }
 
@@ -482,10 +516,10 @@ with_semaphore(basic_semaphore<ExceptionFactory, Clock>& sem, size_t units, Func
 ///       the future returned by with_semaphore() resolves.
 ///
 /// \related semaphore
-template <typename ExceptionFactory, typename Func>
+template <typename ExceptionFactory, typename Clock, typename Func>
 inline
 futurize_t<std::result_of_t<Func()>>
-with_semaphore(basic_semaphore<ExceptionFactory>& sem, size_t units, typename basic_semaphore<ExceptionFactory>::duration timeout, Func&& func) {
+with_semaphore(basic_semaphore<ExceptionFactory, Clock>& sem, size_t units, typename basic_semaphore<ExceptionFactory, Clock>::duration timeout, Func&& func) {
     return get_units(sem, units, timeout).then([func = std::forward<Func>(func)] (auto units) mutable {
         return futurize_apply(std::forward<Func>(func)).finally([units = std::move(units)] {});
     });
@@ -494,6 +528,7 @@ with_semaphore(basic_semaphore<ExceptionFactory>& sem, size_t units, typename ba
 /// default basic_semaphore specialization that throws semaphore specific exceptions
 /// on error conditions.
 using semaphore = basic_semaphore<semaphore_default_exception_factory>;
+using named_semaphore = basic_semaphore<named_semaphore_exception_factory>;
 
 /// @}