LCOV - code coverage report
Current view: top level - src/base/platform - mutex.h (source / functions) Hit Total Coverage
Test: app.info Lines: 7 7 100.0 %
Date: 2019-02-19 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 - a replacement for std::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             : // RecursiveMutex - a replacement for std::recursive_mutex
     111             : //
     112             : // This class is a synchronization primitive that can be used to protect shared
     113             : // data from being simultaneously accessed by multiple threads. A recursive
     114             : // mutex offers exclusive, recursive ownership semantics:
     115             : // - A calling thread owns a recursive mutex for a period of time that starts
     116             : //   when it successfully calls either |Lock()| or |TryLock()|. During this
     117             : //   period, the thread may make additional calls to |Lock()| or |TryLock()|.
     118             : //   The period of ownership ends when the thread makes a matching number of
     119             : //   calls to |Unlock()|.
     120             : // - When a thread owns a recursive mutex, all other threads will block (for
     121             : //   calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if
     122             : //   they attempt to claim ownership of the recursive mutex.
     123             : // - The maximum number of times that a recursive mutex may be locked is
     124             : //   unspecified, but after that number is reached, calls to |Lock()| will
     125             : //   probably abort the process and calls to |TryLock()| return false.
     126             : // The behavior of a program is undefined if a recursive mutex is destroyed
     127             : // while still owned by some thread. The RecursiveMutex class is non-copyable.
     128             : 
     129             : class V8_BASE_EXPORT RecursiveMutex final {
     130             :  public:
     131             :   RecursiveMutex();
     132             :   ~RecursiveMutex();
     133             : 
     134             :   // Locks the mutex. If another thread has already locked the mutex, a call to
     135             :   // |Lock()| will block execution until the lock is acquired. A thread may call
     136             :   // |Lock()| on a recursive mutex repeatedly. Ownership will only be released
     137             :   // after the thread makes a matching number of calls to |Unlock()|.
     138             :   // The behavior is undefined if the mutex is not unlocked before being
     139             :   // destroyed, i.e. some thread still owns it.
     140             :   void Lock();
     141             : 
     142             :   // Unlocks the mutex if its level of ownership is 1 (there was exactly one
     143             :   // more call to |Lock()| than there were calls to unlock() made by this
     144             :   // thread), reduces the level of ownership by 1 otherwise. The mutex must be
     145             :   // locked by the current thread of execution, otherwise, the behavior is
     146             :   // undefined.
     147             :   void Unlock();
     148             : 
     149             :   // Tries to lock the given mutex. Returns whether the mutex was
     150             :   // successfully locked.
     151             :   bool TryLock() V8_WARN_UNUSED_RESULT;
     152             : 
     153             :   // The implementation-defined native handle type.
     154             : #if V8_OS_POSIX
     155             :   typedef pthread_mutex_t NativeHandle;
     156             : #elif V8_OS_WIN
     157             :   typedef CRITICAL_SECTION NativeHandle;
     158             : #endif
     159             : 
     160             :  private:
     161             :   NativeHandle native_handle_;
     162             : #ifdef DEBUG
     163             :   int level_;
     164             : #endif
     165             : 
     166             :   DISALLOW_COPY_AND_ASSIGN(RecursiveMutex);
     167             : };
     168             : 
     169             : 
     170             : // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is
     171             : // called).
     172             : // Usage:
     173             : //   static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER;
     174             : //
     175             : //   void my_function() {
     176             : //     LockGuard<RecursiveMutex> guard(my_mutex.Pointer());
     177             : //     // Do something.
     178             : //   }
     179             : //
     180             : typedef LazyStaticInstance<RecursiveMutex,
     181             :                            DefaultConstructTrait<RecursiveMutex>,
     182             :                            ThreadSafeInitOnceTrait>::type LazyRecursiveMutex;
     183             : 
     184             : #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
     185             : 
     186             : 
     187             : // -----------------------------------------------------------------------------
     188             : // LockGuard
     189             : //
     190             : // This class is a mutex wrapper that provides a convenient RAII-style mechanism
     191             : // for owning a mutex for the duration of a scoped block.
     192             : // When a LockGuard object is created, it attempts to take ownership of the
     193             : // mutex it is given. When control leaves the scope in which the LockGuard
     194             : // object was created, the LockGuard is destructed and the mutex is released.
     195             : // The LockGuard class is non-copyable.
     196             : 
     197             : // Controls whether a LockGuard always requires a valid Mutex or will just
     198             : // ignore it if it's nullptr.
     199             : enum class NullBehavior { kRequireNotNull, kIgnoreIfNull };
     200             : 
     201             : template <typename Mutex, NullBehavior Behavior = NullBehavior::kRequireNotNull>
     202             : class LockGuard final {
     203             :  public:
     204    14917791 :   explicit LockGuard(Mutex* mutex) : mutex_(mutex) {
     205   276983869 :     if (has_mutex()) mutex_->Lock();
     206    14573658 :   }
     207    14573282 :   ~LockGuard() {
     208   276674190 :     if (has_mutex()) mutex_->Unlock();
     209    14573352 :   }
     210             : 
     211             :  private:
     212             :   Mutex* const mutex_;
     213             : 
     214             :   bool V8_INLINE has_mutex() const {
     215             :     DCHECK_IMPLIES(Behavior == NullBehavior::kRequireNotNull,
     216             :                    mutex_ != nullptr);
     217      217690 :     return Behavior == NullBehavior::kRequireNotNull || mutex_ != nullptr;
     218             :   }
     219             : 
     220             :   DISALLOW_COPY_AND_ASSIGN(LockGuard);
     221             : };
     222             : 
     223             : using MutexGuard = LockGuard<Mutex>;
     224             : 
     225             : }  // namespace base
     226             : }  // namespace v8
     227             : 
     228             : #endif  // V8_BASE_PLATFORM_MUTEX_H_

Generated by: LCOV version 1.10