[llvm] r369018 - [Support] Base RWMutex on std::shared_timed_mutex (C++14)

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 15 09:55:23 PDT 2019


Author: d0k
Date: Thu Aug 15 09:55:23 2019
New Revision: 369018

URL: http://llvm.org/viewvc/llvm-project?rev=369018&view=rev
Log:
[Support] Base RWMutex on std::shared_timed_mutex (C++14)

This should have the same semantics. We use std::shared_mutex instead on
MSVC and C++17, std::shared_timed_mutex is less efficient than our
custom implementation on Windows, std::shared_mutex should be faster.

Removed:
    llvm/trunk/lib/Support/RWMutex.cpp
    llvm/trunk/lib/Support/Unix/RWMutex.inc
    llvm/trunk/lib/Support/Windows/RWMutex.inc
Modified:
    llvm/trunk/include/llvm/Support/RWMutex.h
    llvm/trunk/lib/Support/CMakeLists.txt

Modified: llvm/trunk/include/llvm/Support/RWMutex.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/RWMutex.h?rev=369018&r1=369017&r2=369018&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/RWMutex.h (original)
+++ llvm/trunk/include/llvm/Support/RWMutex.h Thu Aug 15 09:55:23 2019
@@ -16,87 +16,33 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/Threading.h"
 #include <cassert>
+#include <mutex>
+#include <shared_mutex>
 
 namespace llvm {
 namespace sys {
 
-    /// Platform agnostic RWMutex class.
-    class RWMutexImpl
-    {
-    /// @name Constructors
-    /// @{
-    public:
-
-      /// Initializes the lock but doesn't acquire it.
-      /// Default Constructor.
-      explicit RWMutexImpl();
-
-    /// @}
-    /// @name Do Not Implement
-    /// @{
-      RWMutexImpl(const RWMutexImpl & original) = delete;
-      RWMutexImpl &operator=(const RWMutexImpl &) = delete;
-    /// @}
-
-      /// Releases and removes the lock
-      /// Destructor
-      ~RWMutexImpl();
-
-    /// @}
-    /// @name Methods
-    /// @{
-    public:
-
-      /// Attempts to unconditionally acquire the lock in reader mode. If the
-      /// lock is held by a writer, this method will wait until it can acquire
-      /// the lock.
-      /// @returns false if any kind of error occurs, true otherwise.
-      /// Unconditionally acquire the lock in reader mode.
-      bool reader_acquire();
-
-      /// Attempts to release the lock in reader mode.
-      /// @returns false if any kind of error occurs, true otherwise.
-      /// Unconditionally release the lock in reader mode.
-      bool reader_release();
-
-      /// Attempts to unconditionally acquire the lock in reader mode. If the
-      /// lock is held by any readers, this method will wait until it can
-      /// acquire the lock.
-      /// @returns false if any kind of error occurs, true otherwise.
-      /// Unconditionally acquire the lock in writer mode.
-      bool writer_acquire();
-
-      /// Attempts to release the lock in writer mode.
-      /// @returns false if any kind of error occurs, true otherwise.
-      /// Unconditionally release the lock in write mode.
-      bool writer_release();
-
-    //@}
-    /// @name Platform Dependent Data
-    /// @{
-    private:
-#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
-      void* data_ = nullptr; ///< We don't know what the data will be
-#endif
-    };
-
     /// SmartMutex - An R/W mutex with a compile time constant parameter that
     /// indicates whether this mutex should become a no-op when we're not
     /// running in multithreaded mode.
     template<bool mt_only>
     class SmartRWMutex {
-      RWMutexImpl impl;
+      // shared_mutex (C++17) is more efficient than shared_timed_mutex (C++14)
+      // on Windows and always available on MSVC.
+#if defined(_MSC_VER) || __cplusplus > 201402L
+      std::shared_mutex impl;
+#else
+      std::shared_timed_mutex impl;
+#endif
       unsigned readers = 0;
       unsigned writers = 0;
 
     public:
-      explicit SmartRWMutex() = default;
-      SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
-      SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
-
       bool lock_shared() {
-        if (!mt_only || llvm_is_multithreaded())
-          return impl.reader_acquire();
+        if (!mt_only || llvm_is_multithreaded()) {
+          impl.lock_shared();
+          return true;
+        }
 
         // Single-threaded debugging code.  This would be racy in multithreaded
         // mode, but provides not sanity checks in single threaded mode.
@@ -105,8 +51,10 @@ namespace sys {
       }
 
       bool unlock_shared() {
-        if (!mt_only || llvm_is_multithreaded())
-          return impl.reader_release();
+        if (!mt_only || llvm_is_multithreaded()) {
+          impl.unlock_shared();
+          return true;
+        }
 
         // Single-threaded debugging code.  This would be racy in multithreaded
         // mode, but provides not sanity checks in single threaded mode.
@@ -116,8 +64,10 @@ namespace sys {
       }
 
       bool lock() {
-        if (!mt_only || llvm_is_multithreaded())
-          return impl.writer_acquire();
+        if (!mt_only || llvm_is_multithreaded()) {
+          impl.lock();
+          return true;
+        }
 
         // Single-threaded debugging code.  This would be racy in multithreaded
         // mode, but provides not sanity checks in single threaded mode.
@@ -127,8 +77,10 @@ namespace sys {
       }
 
       bool unlock() {
-        if (!mt_only || llvm_is_multithreaded())
-          return impl.writer_release();
+        if (!mt_only || llvm_is_multithreaded()) {
+          impl.unlock();
+          return true;
+        }
 
         // Single-threaded debugging code.  This would be racy in multithreaded
         // mode, but provides not sanity checks in single threaded mode.
@@ -142,33 +94,13 @@ namespace sys {
 
     /// ScopedReader - RAII acquisition of a reader lock
     template<bool mt_only>
-    struct SmartScopedReader {
-      SmartRWMutex<mt_only>& mutex;
-
-      explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
-        mutex.lock_shared();
-      }
-
-      ~SmartScopedReader() {
-        mutex.unlock_shared();
-      }
-    };
+    using SmartScopedReader = const std::shared_lock<SmartRWMutex<mt_only>>;
 
     typedef SmartScopedReader<false> ScopedReader;
 
     /// ScopedWriter - RAII acquisition of a writer lock
     template<bool mt_only>
-    struct SmartScopedWriter {
-      SmartRWMutex<mt_only>& mutex;
-
-      explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
-        mutex.lock();
-      }
-
-      ~SmartScopedWriter() {
-        mutex.unlock();
-      }
-    };
+    using SmartScopedWriter = std::lock_guard<SmartRWMutex<mt_only>>;
 
     typedef SmartScopedWriter<false> ScopedWriter;
 

Modified: llvm/trunk/lib/Support/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=369018&r1=369017&r2=369018&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CMakeLists.txt (original)
+++ llvm/trunk/lib/Support/CMakeLists.txt Thu Aug 15 09:55:23 2019
@@ -173,7 +173,6 @@ add_llvm_library(LLVMSupport
   Path.cpp
   Process.cpp
   Program.cpp
-  RWMutex.cpp
   Signals.cpp
   TargetRegistry.cpp
   ThreadLocal.cpp

Removed: llvm/trunk/lib/Support/RWMutex.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/RWMutex.cpp?rev=369017&view=auto
==============================================================================
--- llvm/trunk/lib/Support/RWMutex.cpp (original)
+++ llvm/trunk/lib/Support/RWMutex.cpp (removed)
@@ -1,124 +0,0 @@
-//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the llvm::sys::RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/RWMutex.h"
-#include "llvm/Config/config.h"
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//===          independent code.
-//===----------------------------------------------------------------------===//
-
-#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-// Define all methods as no-ops if threading is explicitly disabled
-
-using namespace llvm;
-using namespace sys;
-
-RWMutexImpl::RWMutexImpl() = default;
-RWMutexImpl::~RWMutexImpl() = default;
-
-bool RWMutexImpl::reader_acquire() { return true; }
-bool RWMutexImpl::reader_release() { return true; }
-bool RWMutexImpl::writer_acquire() { return true; }
-bool RWMutexImpl::writer_release() { return true; }
-
-#else
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
-
-#include <cassert>
-#include <cstdlib>
-#include <pthread.h>
-
-using namespace llvm;
-using namespace sys;
-
-// Construct a RWMutex using pthread calls
-RWMutexImpl::RWMutexImpl()
-{
-  // Declare the pthread_rwlock data structures
-  pthread_rwlock_t* rwlock =
-    static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
-
-#ifdef __APPLE__
-  // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
-  bzero(rwlock, sizeof(pthread_rwlock_t));
-#endif
-
-  // Initialize the rwlock
-  int errorcode = pthread_rwlock_init(rwlock, nullptr);
-  (void)errorcode;
-  assert(errorcode == 0);
-
-  // Assign the data member
-  data_ = rwlock;
-}
-
-// Destruct a RWMutex
-RWMutexImpl::~RWMutexImpl()
-{
-  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
-  assert(rwlock != nullptr);
-  pthread_rwlock_destroy(rwlock);
-  free(rwlock);
-}
-
-bool
-RWMutexImpl::reader_acquire()
-{
-  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
-  assert(rwlock != nullptr);
-
-  int errorcode = pthread_rwlock_rdlock(rwlock);
-  return errorcode == 0;
-}
-
-bool
-RWMutexImpl::reader_release()
-{
-  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
-  assert(rwlock != nullptr);
-
-  int errorcode = pthread_rwlock_unlock(rwlock);
-  return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_acquire()
-{
-  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
-  assert(rwlock != nullptr);
-
-  int errorcode = pthread_rwlock_wrlock(rwlock);
-  return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_release()
-{
-  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
-  assert(rwlock != nullptr);
-
-  int errorcode = pthread_rwlock_unlock(rwlock);
-  return errorcode == 0;
-}
-
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/RWMutex.inc"
-#elif defined( _WIN32)
-#include "Windows/RWMutex.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
-#endif
-#endif

Removed: llvm/trunk/lib/Support/Unix/RWMutex.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/RWMutex.inc?rev=369017&view=auto
==============================================================================
--- llvm/trunk/lib/Support/Unix/RWMutex.inc (original)
+++ llvm/trunk/lib/Support/Unix/RWMutex.inc (removed)
@@ -1,50 +0,0 @@
-//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock  =//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//===          is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-using namespace sys;
-
-// This naive implementation treats readers the same as writers.  This
-// will therefore deadlock if a thread tries to acquire a read lock
-// multiple times.
-
-RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
-
-RWMutexImpl::~RWMutexImpl() {
-  delete static_cast<MutexImpl *>(data_);
-}
-
-bool RWMutexImpl::reader_acquire() {
-  return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::reader_release() {
-  return static_cast<MutexImpl *>(data_)->release();
-}
-
-bool RWMutexImpl::writer_acquire() {
-  return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::writer_release() {
-  return static_cast<MutexImpl *>(data_)->release();
-}
-
-}

Removed: llvm/trunk/lib/Support/Windows/RWMutex.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/RWMutex.inc?rev=369017&view=auto
==============================================================================
--- llvm/trunk/lib/Support/Windows/RWMutex.inc (original)
+++ llvm/trunk/lib/Support/Windows/RWMutex.inc (removed)
@@ -1,128 +0,0 @@
-//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock  =//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Win32 specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//===          is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-
-namespace llvm {
-
-// Windows has slim read-writer lock support on Vista and higher, so we
-// will attempt to load the APIs.  If they exist, we will use them, and
-// if not, we will fall back on critical sections.  When we drop support
-// for XP, we can stop lazy-loading these APIs and just use them directly.
-#if defined(__MINGW32__)
-  // Taken from WinNT.h
-  typedef struct _RTL_SRWLOCK {
-    PVOID Ptr;
-  } RTL_SRWLOCK, *PRTL_SRWLOCK;
-
-  // Taken from WinBase.h
-  typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
-#endif
-
-static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
-
-static bool sHasSRW = false;
-
-static bool loadSRW() {
-  static bool sChecked = false;
-  if (!sChecked) {
-    sChecked = true;
-
-    if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
-      fpInitializeSRWLock =
-        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
-                                               "InitializeSRWLock");
-      fpAcquireSRWLockExclusive =
-        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
-                                               "AcquireSRWLockExclusive");
-      fpAcquireSRWLockShared =
-        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
-                                               "AcquireSRWLockShared");
-      fpReleaseSRWLockExclusive =
-        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
-                                               "ReleaseSRWLockExclusive");
-      fpReleaseSRWLockShared =
-        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
-                                               "ReleaseSRWLockShared");
-
-      if (fpInitializeSRWLock != NULL) {
-        sHasSRW = true;
-      }
-    }
-  }
-  return sHasSRW;
-}
-
-sys::RWMutexImpl::RWMutexImpl() {
-  if (loadSRW()) {
-    data_ = safe_calloc(1, sizeof(SRWLOCK));
-    fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
-  } else {
-    data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
-    InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  }
-}
-
-sys::RWMutexImpl::~RWMutexImpl() {
-  if (!sHasSRW)
-    DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  // Nothing to do in the case of slim reader/writers except free the memory.
-  free(data_);
-}
-
-bool sys::RWMutexImpl::reader_acquire() {
-  if (sHasSRW) {
-    fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
-  } else {
-    EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  }
-  return true;
-}
-
-bool sys::RWMutexImpl::reader_release() {
-  if (sHasSRW) {
-    fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
-  } else {
-    LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  }
-  return true;
-}
-
-bool sys::RWMutexImpl::writer_acquire() {
-  if (sHasSRW) {
-    fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
-  } else {
-    EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  }
-  return true;
-}
-
-bool sys::RWMutexImpl::writer_release() {
-  if (sHasSRW) {
-    fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
-  } else {
-    LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
-  }
-  return true;
-}
-
-
-}




More information about the llvm-commits mailing list