Bug 1867190 - Initialise the PHC allocate delay later r=glandium
[gecko.git] / xpcom / threads / DataMutex.h
blob44f0a3576243359006a427eb601179aeb70100cc
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DataMutex_h__
8 #define DataMutex_h__
10 #include <utility>
11 #include "mozilla/Mutex.h"
12 #include "mozilla/StaticMutex.h"
14 namespace mozilla {
16 // A template to wrap a type with a mutex so that accesses to the type's
17 // data are required to take the lock before accessing it. This ensures
18 // that a mutex is explicitly associated with the data that it protects,
19 // and makes it impossible to access the data without first taking the
20 // associated mutex.
22 // This is based on Rust's std::sync::Mutex, which operates under the
23 // strategy of locking data, rather than code.
25 // Examples:
27 // DataMutex<uint32_t> u32DataMutex(1, "u32DataMutex");
28 // auto x = u32DataMutex.Lock();
29 // *x = 4;
30 // assert(*x, 4u);
32 // DataMutex<nsTArray<uint32_t>> arrayDataMutex("arrayDataMutex");
33 // auto a = arrayDataMutex.Lock();
34 // auto& x = a.ref();
35 // x.AppendElement(1u);
36 // assert(x[0], 1u);
38 template <typename T, typename MutexType>
39 class DataMutexBase {
40 public:
41 template <typename V>
42 class MOZ_STACK_CLASS AutoLockBase {
43 public:
44 V* operator->() const& { return &ref(); }
45 V* operator->() const&& = delete;
47 V& operator*() const& { return ref(); }
48 V& operator*() const&& = delete;
50 // Like RefPtr, make this act like its underlying raw pointer type
51 // whenever it is used in a context where a raw pointer is expected.
52 operator V*() const& { return &ref(); }
54 // Like RefPtr, don't allow implicit conversion of temporary to raw pointer.
55 operator V*() const&& = delete;
57 V& ref() const& {
58 MOZ_ASSERT(mOwner);
59 return mOwner->mValue;
61 V& ref() const&& = delete;
63 AutoLockBase(AutoLockBase&& aOther) : mOwner(aOther.mOwner) {
64 aOther.mOwner = nullptr;
67 ~AutoLockBase() {
68 if (mOwner) {
69 mOwner->mMutex.Unlock();
70 mOwner = nullptr;
74 private:
75 friend class DataMutexBase;
77 AutoLockBase(const AutoLockBase& aOther) = delete;
79 explicit AutoLockBase(DataMutexBase<T, MutexType>* aDataMutex)
80 : mOwner(aDataMutex) {
81 MOZ_ASSERT(!!mOwner);
82 mOwner->mMutex.Lock();
85 DataMutexBase<T, MutexType>* mOwner;
88 using AutoLock = AutoLockBase<T>;
89 using ConstAutoLock = AutoLockBase<const T>;
91 explicit DataMutexBase(const char* aName) : mMutex(aName) {}
93 DataMutexBase(T&& aValue, const char* aName)
94 : mMutex(aName), mValue(std::move(aValue)) {}
96 AutoLock Lock() { return AutoLock(this); }
97 ConstAutoLock ConstLock() { return ConstAutoLock(this); }
99 const MutexType& Mutex() const { return mMutex; }
101 private:
102 MutexType mMutex;
103 T mValue;
106 // Craft a version of StaticMutex that takes a const char* in its ctor.
107 // We need this so it works interchangeably with Mutex which requires a const
108 // char* aName in its ctor.
109 class StaticMutexNameless : public StaticMutex {
110 public:
111 explicit StaticMutexNameless(const char* aName) : StaticMutex() {}
113 private:
114 // Disallow copy construction, `=`, `new`, and `delete` like BaseStaticMutex.
115 #ifdef DEBUG
116 StaticMutexNameless(StaticMutexNameless& aOther);
117 #endif // DEBUG
118 StaticMutexNameless& operator=(StaticMutexNameless* aRhs);
119 static void* operator new(size_t) noexcept(true);
120 static void operator delete(void*);
123 template <typename T>
124 using DataMutex = DataMutexBase<T, Mutex>;
125 template <typename T>
126 using StaticDataMutex = DataMutexBase<T, StaticMutexNameless>;
128 } // namespace mozilla
130 #endif // DataMutex_h__