#pragma once
#include
#include
#include
namespace DB
{
/** SharedMutexHelper class allows to inject specific logic when underlying shared mutex is acquired
* and released.
*
* Example:
*
* class ProfileSharedMutex : public SharedMutexHelper
* {
* public:
* size_t getLockCount() const { return lock_count; }
*
* size_t getSharedLockCount() const { return shared_lock_count; }
*
* private:
* using Base = SharedMutexHelper;
* friend class SharedMutexHelper;
*
* void lockImpl()
* {
* ++lock_count;
* Base::lockImpl();
* }
*
* void lockSharedImpl()
* {
* ++shared_lock_count;
* Base::lockSharedImpl();
* }
*
* std::atomic lock_count = 0;
* std::atomic shared_lock_count = 0;
* };
*/
template
class TSA_CAPABILITY("SharedMutexHelper") SharedMutexHelper
{
public:
// Exclusive ownership
void lock() TSA_ACQUIRE() /// NOLINT
{
static_cast(this)->lockImpl();
}
bool try_lock() TSA_TRY_ACQUIRE(true) /// NOLINT
{
static_cast(this)->tryLockImpl();
}
void unlock() TSA_RELEASE() /// NOLINT
{
static_cast(this)->unlockImpl();
}
// Shared ownership
void lock_shared() TSA_ACQUIRE_SHARED() /// NOLINT
{
static_cast(this)->lockSharedImpl();
}
bool try_lock_shared() TSA_TRY_ACQUIRE_SHARED(true) /// NOLINT
{
static_cast(this)->tryLockSharedImpl();
}
void unlock_shared() TSA_RELEASE_SHARED() /// NOLINT
{
static_cast(this)->unlockSharedImpl();
}
protected:
void lockImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.lock();
}
void tryLockImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.try_lock();
}
void unlockImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.unlock();
}
void lockSharedImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.lock_shared();
}
void tryLockSharedImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.try_lock_shared();
}
void unlockSharedImpl() TSA_NO_THREAD_SAFETY_ANALYSIS
{
mutex.unlock_shared();
}
MutexType mutex;
};
}