#pragma once #include #ifdef OS_LINUX /// Because of futex #include #include #include namespace DB { // Faster implementation of `std::shared_mutex` based on a pair of futexes class TSA_CAPABILITY("SharedMutex") SharedMutex { public: SharedMutex(); ~SharedMutex() = default; SharedMutex(const SharedMutex &) = delete; SharedMutex & operator=(const SharedMutex &) = delete; // Exclusive ownership void lock() TSA_ACQUIRE(); bool try_lock() TSA_TRY_ACQUIRE(true); void unlock() TSA_RELEASE(); // Shared ownership void lock_shared() TSA_ACQUIRE_SHARED(); bool try_lock_shared() TSA_TRY_ACQUIRE_SHARED(true); void unlock_shared() TSA_RELEASE_SHARED(); private: static constexpr UInt64 readers = (1ull << 32ull) - 1ull; // Lower 32 bits of state static constexpr UInt64 writers = ~readers; // Upper 32 bits of state alignas(64) std::atomic state; std::atomic waiters; }; } #else namespace DB { using SharedMutex = std::shared_mutex; } #endif