// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #pragma once #include #include "common/containers.h" // What and why // ============ // // For general code making use of mutexes, use these ceph:: types. // The key requirement is that you make use of the ceph::make_mutex() // and make_recursive_mutex() factory methods, which take a string // naming the mutex for the purposes of the lockdep debug variant. #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN) namespace ceph { // an empty class satisfying the mutex concept struct dummy_mutex { void lock() {} bool try_lock() { return true; } void unlock() {} void lock_shared() {} void unlock_shared() {} }; struct dummy_shared_mutex : dummy_mutex { void lock_shared() {} void unlock_shared() {} }; using mutex = dummy_mutex; using recursive_mutex = dummy_mutex; using shared_mutex = dummy_shared_mutex; // in seastar, we should use a difference interface for enforcing the // semantics of condition_variable template dummy_mutex make_mutex(Args&& ...args) { return {}; } template recursive_mutex make_recursive_mutex(Args&& ...args) { return {}; } template shared_mutex make_shared_mutex(Args&& ...args) { return {}; } #define ceph_mutex_is_locked(m) true #define ceph_mutex_is_locked_by_me(m) true } #else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN) // // For legacy Mutex users that passed recursive=true, use // ceph::make_recursive_mutex. For legacy Mutex users that passed // lockdep=false, use std::mutex directly. #ifdef CEPH_DEBUG_MUTEX // ============================================================================ // debug (lockdep-capable, various sanity checks and asserts) // ============================================================================ // // Note: this is known to cause deadlocks on Windows because // of the winpthreads shared mutex implementation. #include "common/condition_variable_debug.h" #include "common/mutex_debug.h" #include "common/shared_mutex_debug.h" namespace ceph { typedef ceph::mutex_debug mutex; typedef ceph::mutex_recursive_debug recursive_mutex; typedef ceph::condition_variable_debug condition_variable; typedef ceph::shared_mutex_debug shared_mutex; // pass arguments to mutex_debug ctor template mutex make_mutex(Args&& ...args) { return {std::forward(args)...}; } // pass arguments to recursive_mutex_debug ctor template recursive_mutex make_recursive_mutex(Args&& ...args) { return {std::forward(args)...}; } // pass arguments to shared_mutex_debug ctor template shared_mutex make_shared_mutex(Args&& ...args) { return {std::forward(args)...}; } // debug methods #define ceph_mutex_is_locked(m) ((m).is_locked()) #define ceph_mutex_is_not_locked(m) (!(m).is_locked()) #define ceph_mutex_is_rlocked(m) ((m).is_rlocked()) #define ceph_mutex_is_wlocked(m) ((m).is_wlocked()) #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me()) #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me()) } #else // ============================================================================ // release (fast and minimal) // ============================================================================ #include #include // The winpthreads shared mutex implementation is broken. // We'll use boost::shared_mutex instead. // https://github.com/msys2/MINGW-packages/issues/3319 #if __MINGW32__ #include #else #include #endif namespace ceph { typedef std::mutex mutex; typedef std::recursive_mutex recursive_mutex; typedef std::condition_variable condition_variable; #if __MINGW32__ typedef boost::shared_mutex shared_mutex; #else typedef std::shared_mutex shared_mutex; #endif // discard arguments to make_mutex (they are for debugging only) template mutex make_mutex(Args&& ...args) { return {}; } template recursive_mutex make_recursive_mutex(Args&& ...args) { return {}; } template shared_mutex make_shared_mutex(Args&& ...args) { return {}; } // debug methods. Note that these can blindly return true // because any code that does anything other than assert these // are true is broken. #define ceph_mutex_is_locked(m) true #define ceph_mutex_is_not_locked(m) true #define ceph_mutex_is_rlocked(m) true #define ceph_mutex_is_wlocked(m) true #define ceph_mutex_is_locked_by_me(m) true #define ceph_mutex_is_not_locked_by_me(m) true } #endif // CEPH_DEBUG_MUTEX #endif // WITH_SEASTAR namespace ceph { template ceph::containers::tiny_vector make_lock_container( const std::size_t num_instances, LockFactoryT&& lock_factory) { return { num_instances, [&](const std::size_t i, auto emplacer) { // this will be called `num_instances` times new (emplacer.data()) LockT {lock_factory(i)}; } }; } } // namespace ceph