1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00
dxvk/src/util/sync/sync_signal_win32.h

99 lines
2.3 KiB
C
Raw Normal View History

#pragma once
#include <list>
#include "../com/com_include.h"
#include "sync_signal.h"
namespace dxvk::sync {
/**
* \brief Win32 fence
*
* CPU-side fence that also has the
* ability to signal Win32 events.
*/
class Win32Fence final : public Signal {
public:
Win32Fence()
: m_value(0ull) { }
explicit Win32Fence(uint64_t value)
: m_value(value) { }
/**
* \brief Last signaled value
* \returns Last signaled value
*/
uint64_t value() const {
return m_value.load(std::memory_order_acquire);
}
/**
* \brief Notifies signal
*
* In addition to waking up blocked threads, this
* will also signal any queued win32 events with
* a lower or equal value.
* \param [in] value Value to set signal to
*/
void signal(uint64_t value) {
std::unique_lock<std::mutex> lock(m_mutex);
m_value.store(value, std::memory_order_release);
m_cond.notify_all();
for (auto i = m_events.begin(); i != m_events.end(); ) {
if (value >= i->second) {
SetEvent(i->first);
i = m_events.erase(i);
} else {
i++;
}
}
}
/**
* \brief Waits for signal
* \param [in] value The value to wait for
*/
void wait(uint64_t value) {
std::unique_lock<std::mutex> lock(m_mutex);
m_cond.wait(lock, [this, value] {
return value <= m_value.load(std::memory_order_acquire);
});
}
/**
* \brief Sets Win32 event on completion
*
* When the signal gets signaled with a value equal to or
* greater than the given value, the event will be signaled.
* Signals the event immediately if the last signaled value
* is already greater than or equal to the requested value.
* \param [in] event Win32 Event to signal
* \param [in] value Requested signal value
*/
void setEvent(HANDLE event, uint64_t value) {
std::unique_lock<std::mutex> lock(m_mutex);
if (value > this->value())
m_events.push_back({ event, value });
else
SetEvent(event);
}
private:
std::atomic<uint64_t> m_value;
std::mutex m_mutex;
std::condition_variable m_cond;
std::list<std::pair<HANDLE, uint64_t>> m_events;
};
}