mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-14 00:48:44 +01:00
694d6c7f77
Atomic fetch-and-add on unlock is not needed since no other thread can modify the serving counter after the calling thread acquired the lock. May slightly improve performance in games relying on ID3D10Multithread.
41 lines
737 B
C++
41 lines
737 B
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
|
|
#include "../thread.h"
|
|
|
|
namespace dxvk::sync {
|
|
|
|
/**
|
|
* \brief Ticket spinlock
|
|
*
|
|
* A fair spinlock implementation that should
|
|
* be preferred over \ref Spinlock when one of
|
|
* the threads accessing the lock is likely to
|
|
* starve another.
|
|
*/
|
|
class TicketLock {
|
|
|
|
public:
|
|
|
|
void lock() {
|
|
uint32_t ticket = m_counter.fetch_add(1);
|
|
|
|
while (m_serving.load(std::memory_order_acquire) != ticket)
|
|
continue;
|
|
}
|
|
|
|
void unlock() {
|
|
uint32_t serveNext = m_serving.load() + 1;
|
|
m_serving.store(serveNext, std::memory_order_release);
|
|
}
|
|
|
|
private:
|
|
|
|
std::atomic<uint32_t> m_counter = { 0 };
|
|
std::atomic<uint32_t> m_serving = { 0 };
|
|
|
|
};
|
|
|
|
}
|