// Copyright 2013 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_BASE_PLATFORM_MUTEX_H_ #define V8_BASE_PLATFORM_MUTEX_H_ #include <optional> #include "include/v8config.h" #if V8_OS_DARWIN #include <shared_mutex> #endif #if V8_OS_POSIX #include <pthread.h> #endif #include "src/base/base-export.h" #include "src/base/lazy-instance.h" #include "src/base/logging.h" #if V8_OS_WIN #include "src/base/win32-headers.h" #endif #if V8_OS_STARBOARD #include "starboard/common/mutex.h" #include "starboard/common/recursive_mutex.h" #include "starboard/common/rwlock.h" #endif namespace v8 { namespace base { class ConditionVariable; // ---------------------------------------------------------------------------- // Mutex - a replacement for std::mutex // // This class is a synchronization primitive that can be used to protect shared // data from being simultaneously accessed by multiple threads. A mutex offers // exclusive, non-recursive ownership semantics: // - A calling thread owns a mutex from the time that it successfully calls // either |Lock()| or |TryLock()| until it calls |Unlock()|. // - When a thread owns a mutex, all other threads will block (for calls to // |Lock()|) or receive a |false| return value (for |TryLock()|) if they // attempt to claim ownership of the mutex. // A calling thread must not own the mutex prior to calling |Lock()| or // |TryLock()|. The behavior of a program is undefined if a mutex is destroyed // while still owned by some thread. The Mutex class is non-copyable. class V8_BASE_EXPORT Mutex final { … }; // POD Mutex initialized lazily (i.e. the first time Pointer() is called). // Usage: // static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER; // // void my_function() { // MutexGuard guard(my_mutex.Pointer()); // // Do something. // } // LazyMutex; #define LAZY_MUTEX_INITIALIZER … // ----------------------------------------------------------------------------- // RecursiveMutex - a replacement for std::recursive_mutex // // This class is a synchronization primitive that can be used to protect shared // data from being simultaneously accessed by multiple threads. A recursive // mutex offers exclusive, recursive ownership semantics: // - A calling thread owns a recursive mutex for a period of time that starts // when it successfully calls either |Lock()| or |TryLock()|. During this // period, the thread may make additional calls to |Lock()| or |TryLock()|. // The period of ownership ends when the thread makes a matching number of // calls to |Unlock()|. // - When a thread owns a recursive mutex, all other threads will block (for // calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if // they attempt to claim ownership of the recursive mutex. // - The maximum number of times that a recursive mutex may be locked is // unspecified, but after that number is reached, calls to |Lock()| will // probably abort the process and calls to |TryLock()| return false. // The behavior of a program is undefined if a recursive mutex is destroyed // while still owned by some thread. The RecursiveMutex class is non-copyable. class V8_BASE_EXPORT RecursiveMutex final { … }; // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is // called). // Usage: // static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER; // // void my_function() { // LockGuard<RecursiveMutex> guard(my_mutex.Pointer()); // // Do something. // } // LazyRecursiveMutex; #define LAZY_RECURSIVE_MUTEX_INITIALIZER … // ---------------------------------------------------------------------------- // SharedMutex - a replacement for std::shared_mutex // // This class is a synchronization primitive that can be used to protect shared // data from being simultaneously accessed by multiple threads. In contrast to // other mutex types which facilitate exclusive access, a shared_mutex has two // levels of access: // - shared: several threads can share ownership of the same mutex. // - exclusive: only one thread can own the mutex. // Shared mutexes are usually used in situations when multiple readers can // access the same resource at the same time without causing data races, but // only one writer can do so. // The SharedMutex class is non-copyable. class V8_BASE_EXPORT SharedMutex final { … }; // ----------------------------------------------------------------------------- // LockGuard // // This class is a mutex wrapper that provides a convenient RAII-style mechanism // for owning a mutex for the duration of a scoped block. // When a LockGuard object is created, it attempts to take ownership of the // mutex it is given. When control leaves the scope in which the LockGuard // object was created, the LockGuard is destructed and the mutex is released. // The LockGuard class is non-copyable. // Controls whether a LockGuard always requires a valid Mutex or will just // ignore it if it's nullptr. enum class NullBehavior { … }; template <typename Mutex, NullBehavior Behavior = NullBehavior::kRequireNotNull> class V8_NODISCARD LockGuard final { … }; MutexGuard; RecursiveMutexGuard; enum MutexSharedType : bool { … }; template <MutexSharedType kIsShared, NullBehavior Behavior = NullBehavior::kRequireNotNull> class V8_NODISCARD SharedMutexGuard final { … }; template <MutexSharedType kIsShared, NullBehavior Behavior = NullBehavior::kRequireNotNull> class V8_NODISCARD SharedMutexGuardIf final { … }; } // namespace base } // namespace v8 #endif // V8_BASE_PLATFORM_MUTEX_H_