tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Mutex.h (2447B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef threading_Mutex_h
      8 #define threading_Mutex_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/PlatformMutex.h"
     12 #include "mozilla/ThreadLocal.h"
     13 
     14 #include "threading/ThreadId.h"
     15 
     16 namespace js {
     17 
     18 // A MutexId secifies the name and mutex order for a mutex.
     19 //
     20 // The mutex order defines the allowed order of mutex acqusition on a single
     21 // thread. Mutexes must be acquired in strictly increasing order. Mutexes with
     22 // the same order may not be held at the same time by that thread.
     23 struct MutexId {
     24  const char* name;
     25  uint32_t order;
     26 };
     27 
     28 // The Mutex class below wraps mozilla::detail::MutexImpl, but we don't want to
     29 // use public inheritance, and private inheritance is problematic because
     30 // Mutex's friends can access the private parent class as if it was public
     31 // inheritance.  So use a data member, but for Mutex to access the data member
     32 // we must override it and make Mutex a friend.
     33 class MutexImpl : public mozilla::detail::MutexImpl {
     34 protected:
     35  MutexImpl() {}
     36 
     37  friend class Mutex;
     38 };
     39 
     40 // In debug builds, js::Mutex is a wrapper over MutexImpl that checks correct
     41 // locking order is observed.
     42 //
     43 // The class maintains a per-thread stack of currently-held mutexes to enable it
     44 // to check this.
     45 class Mutex {
     46 private:
     47  MutexImpl impl_;
     48 
     49 #ifdef DEBUG
     50  const MutexId id_;
     51  Mutex* prev_ = nullptr;
     52  ThreadId owningThread_;
     53 
     54  static MOZ_THREAD_LOCAL(Mutex*) HeldMutexStack;
     55 #endif
     56 
     57 public:
     58 #ifdef DEBUG
     59  static bool Init();
     60 
     61  explicit Mutex(const MutexId& id) : id_(id) { MOZ_ASSERT(id_.order != 0); }
     62 
     63  void lock();
     64  bool tryLock();
     65  void unlock();
     66  bool isOwnedByCurrentThread() const;
     67  void assertOwnedByCurrentThread() const;
     68 #else
     69  static bool Init() { return true; }
     70 
     71  explicit Mutex(const MutexId& id) {}
     72 
     73  void lock() { impl_.lock(); }
     74  bool tryLock() { return impl_.tryLock(); }
     75  void unlock() { impl_.unlock(); }
     76  void assertOwnedByCurrentThread() const {};
     77 #endif
     78 
     79 private:
     80 #ifdef DEBUG
     81  void preLockChecks() const;
     82  void postLockChecks();
     83  void preUnlockChecks();
     84 #endif
     85 
     86  friend class ConditionVariable;
     87 };
     88 
     89 }  // namespace js
     90 
     91 #endif  // threading_Mutex_h