#pragma once
#include <seastar/core/future.hh>
-#include <seastar/core/circular_buffer.hh>
+#include <seastar/core/chunked_fifo.hh>
namespace seastar {
promise<> pr;
bool for_write;
};
- circular_buffer<waiter> _waiters;
+ chunked_fifo<waiter> _waiters;
public:
shared_mutex() = default;
shared_mutex(shared_mutex&&) = default;
///
/// \return a future that becomes ready when no exclusive access
/// is granted to anyone.
- future<> lock_shared() {
+ future<> lock_shared() noexcept {
if (try_lock_shared()) {
return make_ready_future<>();
}
- _waiters.emplace_back(promise<>(), false);
- return _waiters.back().pr.get_future();
+ try {
+ _waiters.emplace_back(promise<>(), false);
+ return _waiters.back().pr.get_future();
+ } catch (...) {
+ return current_exception_as_future();
+ }
}
/// Try to lock the \c shared_mutex for shared access
///
return false;
}
/// Unlocks a \c shared_mutex after a previous call to \ref lock_shared().
- void unlock_shared() {
+ void unlock_shared() noexcept {
assert(_readers > 0);
--_readers;
wake();
///
/// \return a future that becomes ready when no access, shared or exclusive
/// is granted to anyone.
- future<> lock() {
+ future<> lock() noexcept {
if (try_lock()) {
return make_ready_future<>();
}
- _waiters.emplace_back(promise<>(), true);
- return _waiters.back().pr.get_future();
+ try {
+ _waiters.emplace_back(promise<>(), true);
+ return _waiters.back().pr.get_future();
+ } catch (...) {
+ return current_exception_as_future();
+ }
}
/// Try to lock the \c shared_mutex for exclusive access
///
return false;
}
/// Unlocks a \c shared_mutex after a previous call to \ref lock().
- void unlock() {
+ void unlock() noexcept {
assert(_writer);
_writer = false;
wake();
}
private:
- void wake() {
+ void wake() noexcept {
while (!_waiters.empty()) {
auto& w = _waiters.front();
// note: _writer == false in wake()
///
/// \relates shared_mutex
template <typename Func>
-inline
-futurize_t<std::result_of_t<Func ()>>
-with_shared(shared_mutex& sm, Func&& func) {
+SEASTAR_CONCEPT(
+ requires (std::invocable<Func> && std::is_nothrow_move_constructible_v<Func>)
+ inline
+ futurize_t<std::invoke_result_t<Func>>
+)
+SEASTAR_NO_CONCEPT(
+ inline
+ std::enable_if_t<std::is_nothrow_move_constructible_v<Func>, futurize_t<std::result_of_t<Func ()>>>
+)
+with_shared(shared_mutex& sm, Func&& func) noexcept {
return sm.lock_shared().then([&sm, func = std::forward<Func>(func)] () mutable {
return futurize_invoke(func).finally([&sm] {
sm.unlock_shared();
});
}
+template <typename Func>
+SEASTAR_CONCEPT(
+ requires (std::invocable<Func> && !std::is_nothrow_move_constructible_v<Func>)
+ inline
+ futurize_t<std::invoke_result_t<Func>>
+)
+SEASTAR_NO_CONCEPT(
+ inline
+ std::enable_if_t<!std::is_nothrow_move_constructible_v<Func>, futurize_t<std::result_of_t<Func ()>>>
+)
+with_shared(shared_mutex& sm, Func&& func) noexcept {
+ // FIXME: use a coroutine when c++17 support is dropped
+ try {
+ return do_with(std::forward<Func>(func), [&sm] (Func& func) {
+ return sm.lock_shared().then([&func] {
+ return func();
+ }).finally([&sm] {
+ sm.unlock_shared();
+ });
+ });
+ } catch (...) {
+ return current_exception_as_future();
+ }
+}
+
/// Executes a function while holding exclusive access to a resource.
///
/// Executes a function while holding exclusive access to a resource. When
///
/// \relates shared_mutex
template <typename Func>
-inline
-futurize_t<std::result_of_t<Func ()>>
-with_lock(shared_mutex& sm, Func&& func) {
+SEASTAR_CONCEPT(
+ requires (std::invocable<Func> && std::is_nothrow_move_constructible_v<Func>)
+ inline
+ futurize_t<std::invoke_result_t<Func>>
+)
+SEASTAR_NO_CONCEPT(
+ inline
+ std::enable_if_t<std::is_nothrow_move_constructible_v<Func>, futurize_t<std::result_of_t<Func ()>>>
+)
+with_lock(shared_mutex& sm, Func&& func) noexcept {
return sm.lock().then([&sm, func = std::forward<Func>(func)] () mutable {
return futurize_invoke(func).finally([&sm] {
sm.unlock();
});
}
+
+template <typename Func>
+SEASTAR_CONCEPT(
+ requires (std::invocable<Func> && !std::is_nothrow_move_constructible_v<Func>)
+ inline
+ futurize_t<std::invoke_result_t<Func>>
+)
+SEASTAR_NO_CONCEPT(
+ inline
+ std::enable_if_t<!std::is_nothrow_move_constructible_v<Func>, futurize_t<std::result_of_t<Func ()>>>
+)
+with_lock(shared_mutex& sm, Func&& func) noexcept {
+ // FIXME: use a coroutine when c++17 support is dropped
+ try {
+ return do_with(std::forward<Func>(func), [&sm] (Func& func) {
+ return sm.lock().then([&func] {
+ return func();
+ }).finally([&sm] {
+ sm.unlock();
+ });
+ });
+ } catch (...) {
+ return current_exception_as_future();
+ }
+}
+
/// @}
}