Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file declares the llvm::sys::RWMutex class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_SUPPORT_RWMUTEX_H
  14. #define LLVM_SUPPORT_RWMUTEX_H
  15.  
  16. #include "llvm/Config/llvm-config.h"
  17. #include "llvm/Support/Threading.h"
  18. #include <cassert>
  19. #include <mutex>
  20. #include <shared_mutex>
  21.  
  22. // std::shared_timed_mutex is only availble on macOS 10.12 and later.
  23. #if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
  24. #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
  25. #define LLVM_USE_RW_MUTEX_IMPL
  26. #endif
  27. #endif
  28.  
  29. namespace llvm {
  30. namespace sys {
  31.  
  32. #if defined(LLVM_USE_RW_MUTEX_IMPL)
  33. /// Platform agnostic RWMutex class.
  34. class RWMutexImpl {
  35.   /// @name Constructors
  36.   /// @{
  37. public:
  38.   /// Initializes the lock but doesn't acquire it.
  39.   /// Default Constructor.
  40.   explicit RWMutexImpl();
  41.  
  42.   /// @}
  43.   /// @name Do Not Implement
  44.   /// @{
  45.   RWMutexImpl(const RWMutexImpl &original) = delete;
  46.   RWMutexImpl &operator=(const RWMutexImpl &) = delete;
  47.   /// @}
  48.  
  49.   /// Releases and removes the lock
  50.   /// Destructor
  51.   ~RWMutexImpl();
  52.  
  53.   /// @}
  54.   /// @name Methods
  55.   /// @{
  56. public:
  57.   /// Attempts to unconditionally acquire the lock in reader mode. If the
  58.   /// lock is held by a writer, this method will wait until it can acquire
  59.   /// the lock.
  60.   /// @returns false if any kind of error occurs, true otherwise.
  61.   /// Unconditionally acquire the lock in reader mode.
  62.   bool lock_shared();
  63.  
  64.   /// Attempts to release the lock in reader mode.
  65.   /// @returns false if any kind of error occurs, true otherwise.
  66.   /// Unconditionally release the lock in reader mode.
  67.   bool unlock_shared();
  68.  
  69.   /// Attempts to unconditionally acquire the lock in reader mode. If the
  70.   /// lock is held by any readers, this method will wait until it can
  71.   /// acquire the lock.
  72.   /// @returns false if any kind of error occurs, true otherwise.
  73.   /// Unconditionally acquire the lock in writer mode.
  74.   bool lock();
  75.  
  76.   /// Attempts to release the lock in writer mode.
  77.   /// @returns false if any kind of error occurs, true otherwise.
  78.   /// Unconditionally release the lock in write mode.
  79.   bool unlock();
  80.  
  81.   //@}
  82.   /// @name Platform Dependent Data
  83.   /// @{
  84. private:
  85. #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
  86.   void *data_ = nullptr; ///< We don't know what the data will be
  87. #endif
  88. };
  89. #endif
  90.  
  91. /// SmartMutex - An R/W mutex with a compile time constant parameter that
  92. /// indicates whether this mutex should become a no-op when we're not
  93. /// running in multithreaded mode.
  94. template <bool mt_only> class SmartRWMutex {
  95. #if !defined(LLVM_USE_RW_MUTEX_IMPL)
  96.   std::shared_mutex impl;
  97. #else
  98.   RWMutexImpl impl;
  99. #endif
  100.   unsigned readers = 0;
  101.   unsigned writers = 0;
  102.  
  103. public:
  104.   bool lock_shared() {
  105.     if (!mt_only || llvm_is_multithreaded()) {
  106.       impl.lock_shared();
  107.       return true;
  108.     }
  109.  
  110.     // Single-threaded debugging code.  This would be racy in multithreaded
  111.     // mode, but provides not basic checks in single threaded mode.
  112.     ++readers;
  113.     return true;
  114.   }
  115.  
  116.   bool unlock_shared() {
  117.     if (!mt_only || llvm_is_multithreaded()) {
  118.       impl.unlock_shared();
  119.       return true;
  120.     }
  121.  
  122.     // Single-threaded debugging code.  This would be racy in multithreaded
  123.     // mode, but provides not basic checks in single threaded mode.
  124.     assert(readers > 0 && "Reader lock not acquired before release!");
  125.     --readers;
  126.     return true;
  127.   }
  128.  
  129.   bool lock() {
  130.     if (!mt_only || llvm_is_multithreaded()) {
  131.       impl.lock();
  132.       return true;
  133.     }
  134.  
  135.     // Single-threaded debugging code.  This would be racy in multithreaded
  136.     // mode, but provides not basic checks in single threaded mode.
  137.     assert(writers == 0 && "Writer lock already acquired!");
  138.     ++writers;
  139.     return true;
  140.   }
  141.  
  142.   bool unlock() {
  143.     if (!mt_only || llvm_is_multithreaded()) {
  144.       impl.unlock();
  145.       return true;
  146.     }
  147.  
  148.     // Single-threaded debugging code.  This would be racy in multithreaded
  149.     // mode, but provides not basic checks in single threaded mode.
  150.     assert(writers == 1 && "Writer lock not acquired before release!");
  151.     --writers;
  152.     return true;
  153.   }
  154. };
  155.  
  156. typedef SmartRWMutex<false> RWMutex;
  157.  
  158. /// ScopedReader - RAII acquisition of a reader lock
  159. #if !defined(LLVM_USE_RW_MUTEX_IMPL)
  160. template <bool mt_only>
  161. using SmartScopedReader = const std::shared_lock<SmartRWMutex<mt_only>>;
  162. #else
  163. template <bool mt_only> struct SmartScopedReader {
  164.   SmartRWMutex<mt_only> &mutex;
  165.  
  166.   explicit SmartScopedReader(SmartRWMutex<mt_only> &m) : mutex(m) {
  167.     mutex.lock_shared();
  168.   }
  169.  
  170.   ~SmartScopedReader() { mutex.unlock_shared(); }
  171. };
  172. #endif
  173. typedef SmartScopedReader<false> ScopedReader;
  174.  
  175. /// ScopedWriter - RAII acquisition of a writer lock
  176. #if !defined(LLVM_USE_RW_MUTEX_IMPL)
  177. template <bool mt_only>
  178. using SmartScopedWriter = std::lock_guard<SmartRWMutex<mt_only>>;
  179. #else
  180. template <bool mt_only> struct SmartScopedWriter {
  181.   SmartRWMutex<mt_only> &mutex;
  182.  
  183.   explicit SmartScopedWriter(SmartRWMutex<mt_only> &m) : mutex(m) {
  184.     mutex.lock();
  185.   }
  186.  
  187.   ~SmartScopedWriter() { mutex.unlock(); }
  188. };
  189. #endif
  190. typedef SmartScopedWriter<false> ScopedWriter;
  191.  
  192. } // end namespace sys
  193. } // end namespace llvm
  194.  
  195. #endif // LLVM_SUPPORT_RWMUTEX_H
  196.