From: Sage Weil Date: Fri, 19 Oct 2018 18:42:34 +0000 (-0500) Subject: common/convenience: remove lock helpers X-Git-Tag: v14.1.0~820^2~11 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=1f48fc32db6b9b1936c00d567aa2182895b22077;p=ceph-ci.git common/convenience: remove lock helpers These aren't so useful now that we're in an C++17 world. Signed-off-by: Sage Weil --- diff --git a/src/common/convenience.h b/src/common/convenience.h index c230288675f..ad01d48ba7d 100644 --- a/src/common/convenience.h +++ b/src/common/convenience.h @@ -21,8 +21,6 @@ #include -#include "common/shunique_lock.h" - #include "include/ceph_assert.h" // I despise you. Not you the reader, I'm talking // to the include file. @@ -30,138 +28,6 @@ #ifndef CEPH_COMMON_CONVENIENCE_H #define CEPH_COMMON_CONVENIENCE_H -namespace ceph { - -// Lock Factories -// ============== -// -// I used to, whenever I declared a mutex member variable of a class, -// declare a pile of types like: -// ```cpp -// using unique_lock = ::std::unique_lock; -// ``` -// to avoid having to type that big, long type at every use. It also -// let me change the mutex type later. It's inelegant and breaks down -// if you have more than one type of mutex in the same class. So here -// are some lock factories. -template -inline auto uniquely_lock(Mutex&& m, Args&& ...args) - -> std::unique_lock > { - return std::unique_lock >( - std::forward(m), std::forward(args)... ); -} - -template -inline auto sharingly_lock(Mutex&& m, Args&& ...args) - -> std::shared_lock > { - return - std::shared_lock >( - std::forward(m), std::forward(args)...); -} - -template -inline auto shuniquely_lock(std::unique_lock&& m, Args&& ...args) - -> shunique_lock > { - return shunique_lock >( - std::forward >(m), std::forward(args)...); -} - -template -inline auto shuniquely_lock(std::shared_lock&& m, Args&& ...args) - -> shunique_lock > { - return shunique_lock >( - std::forward >(m), - std::forward(args)...); -} - -template -inline auto shuniquely_lock(Mutex&& m, Args&& ...args) - -> shunique_lock > { - return shunique_lock >( - std::forward(m), std::forward(args)...); -} - -// All right! These two don't work like the others. You cannot do -// `auto l = guardedly_lock(m)` since copy elision before C++17 is -// optional. C++17 makes it mandatory so these workarounds won't be -// needed. -// -// To use this, you'll need to do something like: -// `auto&& l = guardedly_lock(m)` -// This way, we aren't actually copying or moving a value, we're -// binding a reference to a temporary which extends its lifetime until -// the end of the enclosing block. -// -// You may in fact want to use -// `[[gnu::unused]] auto&& l = guardedly_lock(m)` -// To avoid the unused variable warning. Since reference assignment -// doesn't have side effects, normally, this just looks to the -// compiler (whose static analysis is not the sharpest hammer in the -// drawer) like a reference we bind for no reason and never -// use. Perhaps future compilers will be smarter about this, but since -// they'll also implement C++17 people might not care. -// - -template -inline auto guardedly_lock(Mutex&& m) - -> std::lock_guard > { - m.lock(); - // So the way this works is that Copy List Initialization creates - // one and only one Temporary. There is no implicit copy that is - // generally optimized away the way there is if we were to just try - // something like `return std::lock_guard(m)`. - // - // The function then returns this temporary as a prvalue. We cannot - // bind it to a variable, because that would implicitly copy it - // (even if in practice RVO would mean there is no copy), so instead - // the user can bind it to a reference. (It has to be either a const - // lvalue reference or an rvalue reference.) - // - // So we get something analogous to all the others with a mildly - // wonky syntax. The need to use [[gnu::unused]] is honestly the - // worst part. It makes this construction unfortunately rather - // long. - return { std::forward(m), std::adopt_lock }; -} - -template -inline auto guardedly_lock(Mutex&& m, std::adopt_lock_t) - -> std::lock_guard > { - return { std::forward(m), std::adopt_lock }; -} - -template -inline auto with_unique_lock(Mutex&& mutex, Fun&& fun, Args&&... args) - -> decltype(fun(std::forward(args)...)) { - // Yes I know there's a lock guard inside and not a unique lock, but - // the caller doesn't need to know or care about the internal - // details, and the semantics are those of unique locking. - [[gnu::unused]] auto&& l = guardedly_lock(std::forward(mutex)); - return std::forward(fun)(std::forward(args)...); -} - -template -inline auto with_shared_lock(Mutex&& mutex, Fun&& fun, Args&&... args) - -> decltype(fun(std::forward(args)...)) { - auto l = sharingly_lock(std::forward(mutex)); - return std::forward(fun)(std::forward(args)...); -} -} - -// Lock Types -// ---------- -// -// Lock factories are nice, but you still have to type out a huge, -// obnoxious template type when declaring a function that takes or -// returns a lock class. -// -#define UNIQUE_LOCK_T(m) \ - ::std::unique_lock> -#define SHARED_LOCK_T(m) \ - ::std::shared_lock> -#define SHUNIQUE_LOCK_T(m) \ - ::ceph::shunique_lock> - namespace ceph { // boost::optional is wonderful! Unfortunately it lacks a function for // the thing you would most obviously want to do with it: apply a