Commit 1ea8f6a4 authored by Elvin Sindrilaru's avatar Elvin Sindrilaru

COMMON: Add SharedMutex implementation using std::shared_timed_mutex

parent 28112766
......@@ -137,8 +137,8 @@ if (NOT TARGET fmt)
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
endif ()
add_subdirectory(proto)
add_subdirectory(common)
add_subdirectory(proto)
add_subdirectory(misc)
add_subdirectory(authz)
add_subdirectory(fst)
......
......@@ -23,6 +23,13 @@
add_subdirectory(backward-cpp)
# @note We need this here since backward-cpp overwrites the global flags for
# c++11 and something similar happens for the fmt directory. This is also the
# reason why the common subdirectory needs to be the first on the list in the
# main CMakeLists.txt file.
set(CMAKE_CXX_STANDARD 14)
set(CPP_VERSION -std=c++14)
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
......@@ -73,6 +80,7 @@ set(EOSCOMMON_SRCS
StringConversion.cc
CommentLog.cc
RWMutex.cc
SharedMutex.cc
PthreadRWMutex.cc
XrdErrorMap.cc
JeMallocHandler.cc
......@@ -213,7 +221,11 @@ endif()
#-------------------------------------------------------------------------------
if(NOT CLIENT AND Linux)
add_executable(dbmaptestburn dbmaptest/DbMapTestBurn.cc)
add_executable(mutextest mutextest/RWMutexTest.cc RWMutex.cc PthreadRWMutex.cc)
add_executable(mutextest
mutextest/RWMutexTest.cc
RWMutex.cc
SharedMutex.cc
PthreadRWMutex.cc)
add_executable(dbmaptestfunc
dbmaptest/DbMapTestFunc.cc
${DBMAPTEST_SRCS}
......
......@@ -22,6 +22,7 @@
#pragma once
#include "common/Namespace.hh"
#include <stdint.h>
EOSCOMMONNAMESPACE_BEGIN
......
......@@ -21,9 +21,104 @@
************************************************************************/
#include "common/RWMutex.hh"
#include "common/PthreadRWMutex.hh"
#include "common/SharedMutex.hh"
EOSCOMMONNAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
RWMutex::RWMutex(bool prefer_readers)
{
if (getenv("EOS_USE_SHARED_MUTEX")) {
mMutexImpl = static_cast<IRWMutex*>(new SharedMutex());
} else {
mMutexImpl = static_cast<IRWMutex*>(new PthreadRWMutex(prefer_readers));
}
}
//------------------------------------------------------------------------------
// Set the write lock to blocking or not blocking
//------------------------------------------------------------------------------
void
RWMutex::SetBlocking(bool block)
{
mMutexImpl->SetBlocking(block);
}
//------------------------------------------------------------------------------
// Lock for read
//------------------------------------------------------------------------------
void
RWMutex::LockRead()
{
mMutexImpl->LockRead();
}
//------------------------------------------------------------------------------
// Try to read lock the mutex within the timeout
//------------------------------------------------------------------------------
int
RWMutex::TimedRdLock(uint64_t timeout_ns)
{
return mMutexImpl->TimedRdLock(timeout_ns);
}
//------------------------------------------------------------------------------
// Unlock a read lock
//------------------------------------------------------------------------------
void
RWMutex::UnLockRead()
{
mMutexImpl->UnLockRead();
}
//------------------------------------------------------------------------------
// Lock for write
//------------------------------------------------------------------------------
void
RWMutex::LockWrite()
{
mMutexImpl->LockWrite();
}
//------------------------------------------------------------------------------
// Unlock a write lock
//------------------------------------------------------------------------------
void
RWMutex::UnLockWrite()
{
mMutexImpl->UnLockWrite();
}
//------------------------------------------------------------------------------
// Try to write lock the mutex within the timeout
//------------------------------------------------------------------------------
int
RWMutex::TimedWrLock(uint64_t timeout_ns)
{
return mMutexImpl->TimedWrLock(timeout_ns);
}
//------------------------------------------------------------------------------
// Get read lock counter
//------------------------------------------------------------------------------
uint64_t
RWMutex::GetReadLockCounter()
{
return mMutexImpl->GetReadLockCounter();
}
//------------------------------------------------------------------------------
// Get write lock counter
//------------------------------------------------------------------------------
uint64_t
RWMutex::GetWriteLockCounter()
{
return mMutexImpl->GetWriteLockCounter();
}
//------------------------------------------------------------------------------
// ***** Class RWMutexWriteLock *****
//------------------------------------------------------------------------------
......
......@@ -21,8 +21,9 @@
************************************************************************/
#pragma once
#include "common/IRWMutex.hh"
// @todo (esindril): this header should be moved to the source file
#include "common/PthreadRWMutex.hh"
#include <memory>
EOSCOMMONNAMESPACE_BEGIN
......@@ -32,25 +33,27 @@ public:
//----------------------------------------------------------------------------
//! Constructor
// ---------------------------------------------------------------------------
RWMutex(bool prefer_readers = false)
{
mMutexImpl = static_cast<IRWMutex*>(new PthreadRWMutex(prefer_readers));
if (getenv("EOS_PTHREAD_RW_MUTEX")) {
} else {
// todo
}
}
RWMutex(bool prefer_readers = false);
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
~RWMutex() {}
// //----------------------------------------------------------------------------
// //! Copy constructor
// //----------------------------------------------------------------------------
// RWMutex(const RWMutex&) = delete;
// //----------------------------------------------------------------------------
// //! Copy assignment operator
// //----------------------------------------------------------------------------
// RWMutex& operator=(const RWMutex&) = delete;
//----------------------------------------------------------------------------
//! Get raw ptr
//----------------------------------------------------------------------------
IRWMutex* GetRawPtr()
inline IRWMutex* GetRawPtr()
{
return mMutexImpl;
}
......@@ -60,18 +63,12 @@ public:
//!
//! @param block blocking mode
//----------------------------------------------------------------------------
void SetBlocking(bool block)
{
mMutexImpl->SetBlocking(block);
}
void SetBlocking(bool block);
//----------------------------------------------------------------------------
//! Lock for read
//----------------------------------------------------------------------------
void LockRead()
{
mMutexImpl->LockRead();
}
void LockRead();
//----------------------------------------------------------------------------
//! Try to read lock the mutex within the timeout
......@@ -80,34 +77,22 @@ public:
//!
//! @return 0 if succcessful, otherwise error code
//----------------------------------------------------------------------------
int TimedRdLock(uint64_t timeout_ns)
{
return mMutexImpl->TimedRdLock(timeout_ns);
}
int TimedRdLock(uint64_t timeout_ns);
//----------------------------------------------------------------------------
//! Unlock a read lock
//----------------------------------------------------------------------------
void UnLockRead()
{
mMutexImpl->UnLockRead();
}
void UnLockRead();
//----------------------------------------------------------------------------
//! Lock for write
//----------------------------------------------------------------------------
void LockWrite()
{
mMutexImpl->LockWrite();
}
void LockWrite();
//----------------------------------------------------------------------------
//! Unlock a write lock
//----------------------------------------------------------------------------
void UnLockWrite()
{
mMutexImpl->UnLockWrite();
}
void UnLockWrite();
//----------------------------------------------------------------------------
//! Try to write lock the mutex within the timeout
......@@ -116,29 +101,19 @@ public:
//!
//! @return 0 if succcessful, otherwise error code
//----------------------------------------------------------------------------
int TimedWrLock(uint64_t timeout_ns)
{
return mMutexImpl->TimedWrLock(timeout_ns);
}
int TimedWrLock(uint64_t timeout_ns);
//----------------------------------------------------------------------------
//! Get read lock counter
//----------------------------------------------------------------------------
uint64_t GetReadLockCounter()
{
return mMutexImpl->GetReadLockCounter();
}
uint64_t GetReadLockCounter();
//----------------------------------------------------------------------------
//! Get write lock counter
//----------------------------------------------------------------------------
uint64_t GetWriteLockCounter()
{
return mMutexImpl->GetWriteLockCounter();
}
uint64_t GetWriteLockCounter();
private:
IRWMutex* mMutexImpl;
};
......
//------------------------------------------------------------------------------
// File: SharedMutex.cc
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
#include "common/SharedMutex.hh"
EOSCOMMONNAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Lock for read
//------------------------------------------------------------------------------
void
SharedMutex::LockRead()
{
++mRdLockCounter;
mSharedMutex.lock_shared();
}
//------------------------------------------------------------------------------
// Unlock a read lock
//-----------------------------------------------------------------------------
void
SharedMutex::UnLockRead()
{
mSharedMutex.unlock_shared();
}
//------------------------------------------------------------------------------
// Try to read lock the mutex within the timeout
//------------------------------------------------------------------------------
int
SharedMutex::TimedRdLock(uint64_t timeout_ns)
{
std::chrono::nanoseconds ns(timeout_ns);
++mRdLockCounter;
return mSharedMutex.try_lock_shared_for(ns);
}
//------------------------------------------------------------------------------
// Lock for write
//------------------------------------------------------------------------------
void
SharedMutex::LockWrite()
{
++mWrLockCounter;
mSharedMutex.lock();
}
//------------------------------------------------------------------------------
// Unlock a write lock
//------------------------------------------------------------------------------
void
SharedMutex::UnLockWrite()
{
mSharedMutex.unlock();
}
//------------------------------------------------------------------------------
// Try to write lock the mutex within the timeout
//------------------------------------------------------------------------------
int
SharedMutex::TimedWrLock(uint64_t timeout_ns)
{
std::chrono::nanoseconds ns(timeout_ns);
++mWrLockCounter;
return mSharedMutex.try_lock_for(ns);
}
EOSCOMMONNAMESPACE_END
//------------------------------------------------------------------------------
// File: SharedMutex.hh
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
************************************************************************/
#pragma once
#include "common/Namespace.hh"
#include "common/IRWMutex.hh"
#include <shared_mutex>
#include <atomic>
EOSCOMMONNAMESPACE_BEGIN
//------------------------------------------------------------------------------
//! Class SharedMutex - wrapper around std::shared_timed_mutex
//------------------------------------------------------------------------------
class SharedMutex: public IRWMutex
{
public:
//----------------------------------------------------------------------------
//! Constructor
// ---------------------------------------------------------------------------
SharedMutex() = default;
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
~SharedMutex() = default;
//----------------------------------------------------------------------------
//! Move constructor
//----------------------------------------------------------------------------
SharedMutex(SharedMutex&& other) = delete;
//----------------------------------------------------------------------------
//! Move assignment operator
//----------------------------------------------------------------------------
SharedMutex& operator=(SharedMutex&& other) = delete;
//----------------------------------------------------------------------------
//! Copy constructor
//----------------------------------------------------------------------------
SharedMutex(const SharedMutex&) = delete;
//----------------------------------------------------------------------------
//! Copy assignment operator
//----------------------------------------------------------------------------
SharedMutex& operator=(const SharedMutex&) = delete;
//----------------------------------------------------------------------------
//! Lock for read
//----------------------------------------------------------------------------
void LockRead() override;
//----------------------------------------------------------------------------
//! Unlock a read lock
//----------------------------------------------------------------------------
void UnLockRead() override;
//----------------------------------------------------------------------------
//! Try to read lock the mutex within the timeout
//!
//! @param timeout_ns nano seconds timeout
//!
//! @return 0 if succcessful, otherwise error code
//----------------------------------------------------------------------------
int TimedRdLock(uint64_t timeout_ns) override;
//----------------------------------------------------------------------------
//! Lock for write
//----------------------------------------------------------------------------
void LockWrite() override;
//----------------------------------------------------------------------------
//! Unlock a write lock
//----------------------------------------------------------------------------
void UnLockWrite() override;
//----------------------------------------------------------------------------
//! Try to write lock the mutex within the timeout
//!
//! @param timeout_ns nano seconds timeout
//!
//! @return 0 if succcessful, otherwise error code
//----------------------------------------------------------------------------
int TimedWrLock(uint64_t timeout_ns) override;
//----------------------------------------------------------------------------
//! Get Readlock Counter
//----------------------------------------------------------------------------
inline uint64_t GetReadLockCounter() override
{
return mRdLockCounter.load();
}
//----------------------------------------------------------------------------
//! Get Writelock Counter
//----------------------------------------------------------------------------
uint64_t GetWriteLockCounter() override
{
return mWrLockCounter.load();
}
private:
//----------------------------------------------------------------------------
//! Set the write lock to blocking or not blocking
//!
//! @param block blocking mode
//----------------------------------------------------------------------------
inline void SetBlocking(bool block)
{
return; // no supported
}
std::shared_timed_mutex mSharedMutex;
std::atomic<uint64_t> mRdLockCounter; ///< Number of read lock operations
std::atomic<uint64_t> mWrLockCounter; ///< Number of write lock operations
};
EOSCOMMONNAMESPACE_END
......@@ -21,8 +21,6 @@
# * along with this program. If not, see <http://www.gnu.org/licenses/>.*
# ************************************************************************
set(CMAKE_CXX_STANDARD 11)
include_directories(
${CMAKE_SOURCE_DIR}
${OPENSSL_INCLUDE_DIRS}
......
......@@ -21,8 +21,6 @@
# * along with this program. If not, see <http://www.gnu.org/licenses/>.*
# ************************************************************************
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g -O0 -std=c++14 -DHAVE_ATOMICS=1")
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment