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/. */
11 #include "mozilla/Mutex.h"
12 #include "mozilla/StaticMutex.h"
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
22 // This is based on Rust's std::sync::Mutex, which operates under the
23 // strategy of locking data, rather than code.
27 // DataMutex<uint32_t> u32DataMutex(1, "u32DataMutex");
28 // auto x = u32DataMutex.Lock();
32 // DataMutex<nsTArray<uint32_t>> arrayDataMutex("arrayDataMutex");
33 // auto a = arrayDataMutex.Lock();
35 // x.AppendElement(1u);
38 template <typename T
, typename MutexType
>
41 class MOZ_STACK_CLASS AutoLock
{
43 T
* operator->() const& { return &ref(); }
44 T
* operator->() const&& = delete;
46 T
& operator*() const& { return ref(); }
47 T
& operator*() const&& = delete;
49 // Like RefPtr, make this act like its underlying raw pointer type
50 // whenever it is used in a context where a raw pointer is expected.
51 operator T
*() const& { return &ref(); }
53 // Like RefPtr, don't allow implicit conversion of temporary to raw pointer.
54 operator T
*() const&& = delete;
58 return mOwner
->mValue
;
60 T
& ref() const&& = delete;
62 AutoLock(AutoLock
&& aOther
) : mOwner(aOther
.mOwner
) {
63 aOther
.mOwner
= nullptr;
68 mOwner
->mMutex
.Unlock();
74 friend class DataMutexBase
;
76 AutoLock(const AutoLock
& aOther
) = delete;
78 explicit AutoLock(DataMutexBase
<T
, MutexType
>* aDataMutex
)
79 : mOwner(aDataMutex
) {
81 mOwner
->mMutex
.Lock();
84 DataMutexBase
<T
, MutexType
>* mOwner
;
87 explicit DataMutexBase(const char* aName
) : mMutex(aName
) {}
89 DataMutexBase(T
&& aValue
, const char* aName
)
90 : mMutex(aName
), mValue(std::move(aValue
)) {}
92 AutoLock
Lock() { return AutoLock(this); }
94 const MutexType
& Mutex() const { return mMutex
; }
101 // Craft a version of StaticMutex that takes a const char* in its ctor.
102 // We need this so it works interchangeably with Mutex which requires a const
103 // char* aName in its ctor.
104 class StaticMutexNameless
: public StaticMutex
{
106 explicit StaticMutexNameless(const char* aName
) : StaticMutex() {}
109 // Disallow copy construction, `=`, `new`, and `delete` like BaseStaticMutex.
111 StaticMutexNameless(StaticMutexNameless
& aOther
);
113 StaticMutexNameless
& operator=(StaticMutexNameless
* aRhs
);
114 static void* operator new(size_t) noexcept(true);
115 static void operator delete(void*);
118 template <typename T
>
119 using DataMutex
= DataMutexBase
<T
, Mutex
>;
120 template <typename T
>
121 using StaticDataMutex
= DataMutexBase
<T
, StaticMutexNameless
>;
123 } // namespace mozilla
125 #endif // DataMutex_h__