Loading...
Searching...
No Matches
spinMutex.h
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_SPIN_MUTEX_H
8#define PXR_BASE_TF_SPIN_MUTEX_H
9
10#include "pxr/pxr.h"
11#include "pxr/base/tf/api.h"
12
13#include "pxr/base/arch/hints.h"
15
16#include <atomic>
17#include <utility>
18
19PXR_NAMESPACE_OPEN_SCOPE
20
43{
44public:
45
47 TfSpinMutex() : _lockState(false) {}
48
51 struct DeferAcquire {};
52
54 static constexpr DeferAcquire deferAcquire {};
55
58 struct ScopedLock {
59
61 explicit ScopedLock(TfSpinMutex &m) : _mutex(&m) {
62 Acquire();
63 }
64
68
70 ScopedLock() = default;
71
74 ScopedLock(ScopedLock &&other) noexcept
75 : _mutex(std::exchange(other._mutex, nullptr))
76 , _acquired(std::exchange(other._acquired, false)) {}
77
82 ScopedLock &operator=(ScopedLock &&other) noexcept {
83 if (this != &other) {
84 Release();
85 _mutex = std::exchange(other._mutex, nullptr);
86 _acquired = std::exchange(other._acquired, false);
87 }
88 return *this;
89 }
90
93 Release();
94 }
95
99 Release();
100 _mutex = &m;
101 Acquire();
102 }
103
106 void Release() {
107 if (_acquired) {
108 _Release();
109 }
110 }
111
114 void Acquire() {
115 TF_DEV_AXIOM(_mutex);
116 TF_DEV_AXIOM(!_acquired);
117 _mutex->Acquire();
118 _acquired = true;
119 }
120
125 Release();
126 _mutex = &m;
127 return TryAcquire();
128 }
129
133 bool TryAcquire() {
134 TF_DEV_AXIOM(_mutex);
135 TF_DEV_AXIOM(!_acquired);
136 _acquired = _mutex->TryAcquire();
137 return _acquired;
138 }
139
140 private:
141
142 void _Release() {
143 TF_DEV_AXIOM(_acquired);
144 _mutex->Release();
145 _acquired = false;
146 }
147
148 TfSpinMutex *_mutex = nullptr;
149 bool _acquired = false;
150 };
151
156 inline bool TryAcquire() {
157 return _lockState.exchange(true, std::memory_order_acquire) == false;
158 }
159
163 void Acquire() {
164 if (ARCH_LIKELY(TryAcquire())) {
165 return;
166 }
167 _AcquireContended();
168 }
169
171 inline void Release() {
172 _lockState.store(false, std::memory_order_release);
173 }
174
175private:
176
177 TF_API void _AcquireContended();
178
179 std::atomic<bool> _lockState;
180};
181
182PXR_NAMESPACE_CLOSE_SCOPE
183
184#endif // PXR_BASE_TF_SPIN_MUTEX_H
This class implements a simple spin lock that emphasizes throughput when there is little to no conten...
Definition: spinMutex.h:43
TfSpinMutex()
Construct a mutex, initially unlocked.
Definition: spinMutex.h:47
static constexpr DeferAcquire deferAcquire
Tag value for deferred-acquisition ScopedLock construction.
Definition: spinMutex.h:54
void Release()
Release this thread's lock on this mutex.
Definition: spinMutex.h:171
void Acquire()
Acquire a lock on this mutex.
Definition: spinMutex.h:163
bool TryAcquire()
Acquire a lock on this mutex if it is not currently held by another thread.
Definition: spinMutex.h:156
Tag type for constructing a ScopedLock associated with a mutex but not yet acquired.
Definition: spinMutex.h:51
Stripped down version of diagnostic.h that doesn't define std::string.
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition: diagnostic.h:205
Compiler hints.
Scoped lock utility class.
Definition: spinMutex.h:58
void Acquire(TfSpinMutex &m)
If the current scoped lock is acquired, Release() it, then associate this lock with m and acquire a l...
Definition: spinMutex.h:98
ScopedLock(ScopedLock &&other) noexcept
Construct a new lock taking the other lock's mutex association and acquisition state.
Definition: spinMutex.h:74
ScopedLock()=default
Construct a scoped lock not associated with a mutex.
void Release()
Release the currently required lock on the associated mutex.
Definition: spinMutex.h:106
ScopedLock(TfSpinMutex &m)
Construct a scoped lock for mutex m and acquire a lock.
Definition: spinMutex.h:61
ScopedLock & operator=(ScopedLock &&other) noexcept
If this is not the same object as other, Release(), take the other lock's mutex association and acqui...
Definition: spinMutex.h:82
void Acquire()
Acquire a lock on this lock's associated mutex.
Definition: spinMutex.h:114
~ScopedLock()
If this scoped lock is acquired, Release() it.
Definition: spinMutex.h:92
bool TryAcquire(TfSpinMutex &m)
If the current scoped lock is acquired, Release() it, then associate this lock with m and try to acqu...
Definition: spinMutex.h:124
bool TryAcquire()
Try to acquire a lock on this lock's associated mutex.
Definition: spinMutex.h:133
ScopedLock(TfSpinMutex &m, TfSpinMutex::DeferAcquire)
Construct a scoped lock associated with mutex m but not yet acquired.
Definition: spinMutex.h:67