static_cast<tri_mutex*>(this)->unlock_for_excl();
}
-seastar::future<> excl_lock_from_read::lock()
+void excl_lock_from_read::lock()
{
static_cast<tri_mutex*>(this)->promote_from_read();
- return seastar::now();
}
void excl_lock_from_read::unlock()
static_cast<tri_mutex*>(this)->demote_to_read();
}
-seastar::future<> excl_lock_from_write::lock()
+void excl_lock_from_write::lock()
{
static_cast<tri_mutex*>(this)->promote_from_write();
- return seastar::now();
}
void excl_lock_from_write::unlock()
static_cast<tri_mutex*>(this)->demote_to_write();
}
-seastar::future<> excl_lock_from_excl::lock()
-{
- return seastar::now();
-}
-
-void excl_lock_from_excl::unlock()
-{
-}
-
tri_mutex::~tri_mutex()
{
assert(!is_acquired());
// promote from read to excl
class excl_lock_from_read {
public:
- seastar::future<> lock();
+ void lock();
void unlock();
};
// promote from write to excl
class excl_lock_from_write {
public:
- seastar::future<> lock();
- void unlock();
-};
-
-// promote from excl to excl
-class excl_lock_from_excl {
-public:
- seastar::future<> lock();
+ void lock();
void unlock();
};
/// - readers
/// - writers
/// - exclusive users
+///
+/// For lock promotion, a read or a write lock is only allowed to be promoted
+/// atomically upon the first locking.
class tri_mutex : private read_lock,
write_lock,
excl_lock,
excl_lock_from_read,
- excl_lock_from_write,
- excl_lock_from_excl
+ excl_lock_from_write
{
public:
tri_mutex() = default;
excl_lock_from_write& excl_from_write() {
return *this;
}
- excl_lock_from_excl& excl_from_excl() {
- return *this;
- }
// for shared readers
seastar::future<> lock_for_read();
bool recovery_read_marker = false;
template <typename Lock, typename Func>
- auto _with_lock(Lock&& lock, Func&& func) {
+ auto _with_lock(Lock& lock, Func&& func) {
Ref obc = this;
return lock.lock().then([&lock, func = std::forward<Func>(func), obc]() mutable {
return seastar::futurize_invoke(func).finally([&lock, obc] {
});
}
+ template <typename Lock, typename Func>
+ auto _with_promoted_lock(Lock& lock, Func&& func) {
+ Ref obc = this;
+ lock.lock();
+ return seastar::futurize_invoke(func).finally([&lock, obc] {
+ lock.unlock();
+ });
+ }
+
boost::intrusive::list_member_hook<> obc_accessing_hook;
uint64_t list_link_cnt = 0;
bool fully_loaded = false;
auto wrapper = ::crimson::interruptible::interruptor<InterruptCond>::wrap_function(std::forward<Func>(func));
switch (Type) {
case RWState::RWWRITE:
- return _with_lock(lock.excl_from_write(), std::move(wrapper));
+ return _with_promoted_lock(lock.excl_from_write(), std::move(wrapper));
case RWState::RWREAD:
- return _with_lock(lock.excl_from_read(), std::move(wrapper));
+ return _with_promoted_lock(lock.excl_from_read(), std::move(wrapper));
case RWState::RWEXCL:
- return _with_lock(lock.excl_from_excl(), std::move(wrapper));
+ return seastar::futurize_invoke(std::move(wrapper));
case RWState::RWNONE:
return _with_lock(lock.for_excl(), std::move(wrapper));
default:
} else {
switch (Type) {
case RWState::RWWRITE:
- return _with_lock(lock.excl_from_write(), std::forward<Func>(func));
+ return _with_promoted_lock(lock.excl_from_write(), std::forward<Func>(func));
case RWState::RWREAD:
- return _with_lock(lock.excl_from_read(), std::forward<Func>(func));
+ return _with_promoted_lock(lock.excl_from_read(), std::forward<Func>(func));
case RWState::RWEXCL:
- return _with_lock(lock.excl_from_excl(), std::forward<Func>(func));
+ return seastar::futurize_invoke(std::forward<Func>(func));
case RWState::RWNONE:
return _with_lock(lock.for_excl(), std::forward<Func>(func));
default: