LCOV - code coverage report
Current view: top level - src/base/platform - mutex.h (source / functions) Hit Total Coverage
Test: app.info Lines: 6 6 100.0 %
Date: 2019-01-20 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_BASE_PLATFORM_MUTEX_H_
       6             : #define V8_BASE_PLATFORM_MUTEX_H_
       7             : 
       8             : #include "src/base/base-export.h"
       9             : #include "src/base/lazy-instance.h"
      10             : #if V8_OS_WIN
      11             : #include "src/base/win32-headers.h"
      12             : #endif
      13             : #include "src/base/logging.h"
      14             : 
      15             : #if V8_OS_POSIX
      16             : #include <pthread.h>  // NOLINT
      17             : #endif
      18             : 
      19             : namespace v8 {
      20             : namespace base {
      21             : 
      22             : // ----------------------------------------------------------------------------
      23             : // Mutex
      24             : //
      25             : // This class is a synchronization primitive that can be used to protect shared
      26             : // data from being simultaneously accessed by multiple threads. A mutex offers
      27             : // exclusive, non-recursive ownership semantics:
      28             : // - A calling thread owns a mutex from the time that it successfully calls
      29             : //   either |Lock()| or |TryLock()| until it calls |Unlock()|.
      30             : // - When a thread owns a mutex, all other threads will block (for calls to
      31             : //   |Lock()|) or receive a |false| return value (for |TryLock()|) if they
      32             : //   attempt to claim ownership of the mutex.
      33             : // A calling thread must not own the mutex prior to calling |Lock()| or
      34             : // |TryLock()|. The behavior of a program is undefined if a mutex is destroyed
      35             : // while still owned by some thread. The Mutex class is non-copyable.
      36             : 
      37             : class V8_BASE_EXPORT Mutex final {
      38             :  public:
      39             :   Mutex();
      40             :   ~Mutex();
      41             : 
      42             :   // Locks the given mutex. If the mutex is currently unlocked, it becomes
      43             :   // locked and owned by the calling thread, and immediately. If the mutex
      44             :   // is already locked by another thread, suspends the calling thread until
      45             :   // the mutex is unlocked.
      46             :   void Lock();
      47             : 
      48             :   // Unlocks the given mutex. The mutex is assumed to be locked and owned by
      49             :   // the calling thread on entrance.
      50             :   void Unlock();
      51             : 
      52             :   // Tries to lock the given mutex. Returns whether the mutex was
      53             :   // successfully locked.
      54             :   bool TryLock() V8_WARN_UNUSED_RESULT;
      55             : 
      56             :   // The implementation-defined native handle type.
      57             : #if V8_OS_POSIX
      58             :   typedef pthread_mutex_t NativeHandle;
      59             : #elif V8_OS_WIN
      60             :   typedef SRWLOCK NativeHandle;
      61             : #endif
      62             : 
      63             :   NativeHandle& native_handle() {
      64             :     return native_handle_;
      65             :   }
      66             :   const NativeHandle& native_handle() const {
      67             :     return native_handle_;
      68             :   }
      69             : 
      70             :  private:
      71             :   NativeHandle native_handle_;
      72             : #ifdef DEBUG
      73             :   int level_;
      74             : #endif
      75             : 
      76             :   V8_INLINE void AssertHeldAndUnmark() {
      77             : #ifdef DEBUG
      78             :     DCHECK_EQ(1, level_);
      79             :     level_--;
      80             : #endif
      81             :   }
      82             : 
      83             :   V8_INLINE void AssertUnheldAndMark() {
      84             : #ifdef DEBUG
      85             :     DCHECK_EQ(0, level_);
      86             :     level_++;
      87             : #endif
      88             :   }
      89             : 
      90             :   friend class ConditionVariable;
      91             : 
      92             :   DISALLOW_COPY_AND_ASSIGN(Mutex);
      93             : };
      94             : 
      95             : // POD Mutex initialized lazily (i.e. the first time Pointer() is called).
      96             : // Usage:
      97             : //   static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
      98             : //
      99             : //   void my_function() {
     100             : //     MutexGuard guard(my_mutex.Pointer());
     101             : //     // Do something.
     102             : //   }
     103             : //
     104             : typedef LazyStaticInstance<Mutex, DefaultConstructTrait<Mutex>,
     105             :                            ThreadSafeInitOnceTrait>::type LazyMutex;
     106             : 
     107             : #define LAZY_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
     108             : 
     109             : 
     110             : // -----------------------------------------------------------------------------
     111             : // RecursiveMutex
     112             : //
     113             : // This class is a synchronization primitive that can be used to protect shared
     114             : // data from being simultaneously accessed by multiple threads. A recursive
     115             : // mutex offers exclusive, recursive ownership semantics:
     116             : // - A calling thread owns a recursive mutex for a period of time that starts
     117             : //   when it successfully calls either |Lock()| or |TryLock()|. During this
     118             : //   period, the thread may make additional calls to |Lock()| or |TryLock()|.
     119             : //   The period of ownership ends when the thread makes a matching number of
     120             : //   calls to |Unlock()|.
     121             : // - When a thread owns a recursive mutex, all other threads will block (for
     122             : //   calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if
     123             : //   they attempt to claim ownership of the recursive mutex.
     124             : // - The maximum number of times that a recursive mutex may be locked is
     125             : //   unspecified, but after that number is reached, calls to |Lock()| will
     126             : //   probably abort the process and calls to |TryLock()| return false.
     127             : // The behavior of a program is undefined if a recursive mutex is destroyed
     128             : // while still owned by some thread. The RecursiveMutex class is non-copyable.
     129             : 
     130             : class V8_BASE_EXPORT RecursiveMutex final {
     131             :  public:
     132             :   RecursiveMutex();
     133             :   ~RecursiveMutex();
     134             : 
     135             :   // Locks the mutex. If another thread has already locked the mutex, a call to
     136             :   // |Lock()| will block execution until the lock is acquired. A thread may call
     137             :   // |Lock()| on a recursive mutex repeatedly. Ownership will only be released
     138             :   // after the thread makes a matching number of calls to |Unlock()|.
     139             :   // The behavior is undefined if the mutex is not unlocked before being
     140             :   // destroyed, i.e. some thread still owns it.
     141             :   void Lock();
     142             : 
     143             :   // Unlocks the mutex if its level of ownership is 1 (there was exactly one
     144             :   // more call to |Lock()| than there were calls to unlock() made by this
     145             :   // thread), reduces the level of ownership by 1 otherwise. The mutex must be
     146             :   // locked by the current thread of execution, otherwise, the behavior is
     147             :   // undefined.
     148             :   void Unlock();
     149             : 
     150             :   // Tries to lock the given mutex. Returns whether the mutex was
     151             :   // successfully locked.
     152             :   bool TryLock() V8_WARN_UNUSED_RESULT;
     153             : 
     154             :   // The implementation-defined native handle type.
     155             : #if V8_OS_POSIX
     156             :   typedef pthread_mutex_t NativeHandle;
     157             : #elif V8_OS_WIN
     158             :   typedef CRITICAL_SECTION NativeHandle;
     159             : #endif
     160             : 
     161             :   NativeHandle& native_handle() {
     162             :     return native_handle_;
     163             :   }
     164             :   const NativeHandle& native_handle() const {
     165             :     return native_handle_;
     166             :   }
     167             : 
     168             :  private:
     169             :   NativeHandle native_handle_;
     170             : #ifdef DEBUG
     171             :   int level_;
     172             : #endif
     173             : 
     174             :   DISALLOW_COPY_AND_ASSIGN(RecursiveMutex);
     175             : };
     176             : 
     177             : 
     178             : // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is
     179             : // called).
     180             : // Usage:
     181             : //   static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER;
     182             : //
     183             : //   void my_function() {
     184             : //     LockGuard<RecursiveMutex> guard(my_mutex.Pointer());
     185             : //     // Do something.
     186             : //   }
     187             : //
     188             : typedef LazyStaticInstance<RecursiveMutex,
     189             :                            DefaultConstructTrait<RecursiveMutex>,
     190             :                            ThreadSafeInitOnceTrait>::type LazyRecursiveMutex;
     191             : 
     192             : #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
     193             : 
     194             : 
     195             : // -----------------------------------------------------------------------------
     196             : // LockGuard
     197             : //
     198             : // This class is a mutex wrapper that provides a convenient RAII-style mechanism
     199             : // for owning a mutex for the duration of a scoped block.
     200             : // When a LockGuard object is created, it attempts to take ownership of the
     201             : // mutex it is given. When control leaves the scope in which the LockGuard
     202             : // object was created, the LockGuard is destructed and the mutex is released.
     203             : // The LockGuard class is non-copyable.
     204             : 
     205             : // Controls whether a LockGuard always requires a valid Mutex or will just
     206             : // ignore it if it's nullptr.
     207             : enum class NullBehavior { kRequireNotNull, kIgnoreIfNull };
     208             : 
     209             : template <typename Mutex, NullBehavior Behavior = NullBehavior::kRequireNotNull>
     210             : class LockGuard final {
     211             :  public:
     212    15548083 :   explicit LockGuard(Mutex* mutex) : mutex_(mutex) {
     213             :     if (Behavior == NullBehavior::kRequireNotNull || mutex_ != nullptr) {
     214   344155217 :       mutex_->Lock();
     215             :     }
     216    15137048 :   }
     217    15136561 :   ~LockGuard() {
     218   343829560 :     if (mutex_ != nullptr) mutex_->Unlock();
     219    15136494 :   }
     220             : 
     221             :  private:
     222             :   Mutex* mutex_;
     223             : 
     224             :   DISALLOW_COPY_AND_ASSIGN(LockGuard);
     225             : };
     226             : 
     227             : using MutexGuard = LockGuard<Mutex>;
     228             : 
     229             : }  // namespace base
     230             : }  // namespace v8
     231             : 
     232             : #endif  // V8_BASE_PLATFORM_MUTEX_H_

Generated by: LCOV version 1.10