1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 11:52:12 +01:00

[util] Introduce CallbackFence

This commit is contained in:
Philip Rebohle 2021-08-02 19:09:23 +02:00
parent 5844315853
commit 893da94fb3
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <atomic> #include <atomic>
#include <functional>
#include <list>
#include "../rc/util_rc.h" #include "../rc/util_rc.h"
@ -89,5 +91,70 @@ namespace dxvk::sync {
dxvk::condition_variable m_cond; dxvk::condition_variable m_cond;
}; };
/**
* \brief Callback signal
*
* CPU-side fence with the ability to call a
* function when signaled to a given value.
*/
class CallbackFence final : public Signal {
public:
CallbackFence()
: m_value(0ull) { }
explicit CallbackFence(uint64_t value)
: m_value(value) { }
uint64_t value() const {
return m_value.load(std::memory_order_acquire);
}
void signal(uint64_t value) {
std::unique_lock<dxvk::mutex> lock(m_mutex);
m_value.store(value, std::memory_order_release);
m_cond.notify_all();
for (auto i = m_callbacks.begin(); i != m_callbacks.end(); ) {
if (value >= i->first) {
i->second();
i = m_callbacks.erase(i);
} else {
i++;
}
}
}
void wait(uint64_t value) {
std::unique_lock<dxvk::mutex> lock(m_mutex);
m_cond.wait(lock, [this, value] {
return value <= m_value.load(std::memory_order_acquire);
});
}
template<typename Fn>
void setCallback(uint64_t value, Fn&& proc) {
std::unique_lock<dxvk::mutex> lock(m_mutex);
if (value > this->value())
m_callbacks.emplace_back(std::piecewise_construct,
std::make_tuple(value),
std::make_tuple(proc));
else
proc();
}
private:
std::atomic<uint64_t> m_value;
dxvk::mutex m_mutex;
dxvk::condition_variable m_cond;
std::list<std::pair<uint64_t, std::function<void ()>>> m_callbacks;
};
} }