summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h b/src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h
new file mode 100644
index 00000000..27157929
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/util/sync/sync_spinlock.h
@@ -0,0 +1,69 @@
+#pragma once
+
+#include <atomic>
+
+#include "../thread.h"
+
+#include "../util_bit.h"
+#include "../util_likely.h"
+
+namespace dxvk::sync {
+
+ /**
+ * \brief Generic spin function
+ *
+ * Blocks calling thread until a condition becomes
+ * \c true, calling \c yield every few iterations.
+ * \param [in] spinCount Number of probes between each yield
+ * \param [in] fn Condition to test
+ */
+ template<typename Fn>
+ void spin(uint32_t spinCount, const Fn& fn) {
+ while (unlikely(!fn())) {
+ for (uint32_t i = 1; i < spinCount; i++) {
+ _mm_pause();
+ if (fn())
+ return;
+ }
+
+ dxvk::this_thread::yield();
+ }
+ }
+
+ /**
+ * \brief Spin lock
+ *
+ * A low-overhead spin lock which can be used to
+ * protect data structures for a short duration
+ * in case the structure is not likely contested.
+ */
+ class Spinlock {
+
+ public:
+
+ Spinlock() { }
+ ~Spinlock() { }
+
+ Spinlock (const Spinlock&) = delete;
+ Spinlock& operator = (const Spinlock&) = delete;
+
+ void lock() {
+ spin(200, [this] { return try_lock(); });
+ }
+
+ void unlock() {
+ m_lock.store(0, std::memory_order_release);
+ }
+
+ bool try_lock() {
+ return likely(!m_lock.load())
+ && likely(!m_lock.exchange(1, std::memory_order_acquire));
+ }
+
+ private:
+
+ std::atomic<uint32_t> m_lock = { 0 };
+
+ };
+
+}