1
0
mirror of synced 2025-02-17 18:59:21 +01:00

impr: Added once execution and task progress increment helpers

This commit is contained in:
WerWolv 2024-02-23 17:47:40 +01:00
parent e6854d6a6a
commit a271658154
2 changed files with 54 additions and 1 deletions

View File

@ -9,6 +9,7 @@
#include <memory>
#include <list>
#include <condition_variable>
#include <source_location>
namespace hex {
@ -33,6 +34,7 @@ namespace hex {
*/
void update(u64 value);
void update() const;
void increment();
/**
* @brief Sets the maximum value of the task
@ -149,6 +151,13 @@ namespace hex {
*/
static void doLater(const std::function<void()> &function);
/**
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
* @param function Function to be executed
* @param location Source location of the function call. This is used to make sure repeated calls to the function at the same location are only executed once
*/
static void doLaterOnce(const std::function<void()> &function, std::source_location location = std::source_location::current());
/**
* @brief Creates a callback that will be executed when all tasks are finished
* @param function Function to be executed

View File

@ -16,14 +16,41 @@
#include <pthread.h>
#endif
namespace {
struct SourceLocationWrapper {
std::source_location location;
bool operator==(const SourceLocationWrapper &other) const {
return location.file_name() == other.location.file_name() &&
location.function_name() == other.location.function_name() &&
location.column() == other.location.column() &&
location.line() == other.location.line();
}
};
}
template<>
struct std::hash<SourceLocationWrapper> {
std::size_t operator()(const SourceLocationWrapper& s) const noexcept {
auto h1 = std::hash<std::string>{}(s.location.file_name());
auto h2 = std::hash<std::string>{}(s.location.function_name());
auto h3 = std::hash<u32>{}(s.location.column());
auto h4 = std::hash<u32>{}(s.location.line());
return (h1 << 0) ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3);
}
};
namespace hex {
namespace {
std::mutex s_deferredCallsMutex, s_tasksFinishedMutex;
std::recursive_mutex s_deferredCallsMutex, s_tasksFinishedMutex;
std::list<std::shared_ptr<Task>> s_tasks, s_taskQueue;
std::list<std::function<void()>> s_deferredCalls;
std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls;
std::list<std::function<void()>> s_tasksFinishedCallbacks;
std::mutex s_queueMutex;
@ -77,6 +104,13 @@ namespace hex {
throw TaskInterruptor();
}
void Task::increment() {
m_currValue.fetch_add(1, std::memory_order_relaxed);
if (m_shouldInterrupt.load(std::memory_order_relaxed)) [[unlikely]]
throw TaskInterruptor();
}
void Task::setMaxValue(u64 value) {
m_maxValue = value;
@ -289,6 +323,7 @@ namespace hex {
s_taskQueue.clear();
s_deferredCalls.clear();
s_onceDeferredCalls.clear();
s_tasksFinishedCallbacks.clear();
}
@ -368,13 +403,22 @@ namespace hex {
s_deferredCalls.push_back(function);
}
void TaskManager::doLaterOnce(const std::function<void()> &function, std::source_location location) {
std::scoped_lock lock(s_deferredCallsMutex);
s_onceDeferredCalls[SourceLocationWrapper{ location }] = function;
}
void TaskManager::runDeferredCalls() {
std::scoped_lock lock(s_deferredCallsMutex);
for (const auto &call : s_deferredCalls)
call();
for (const auto &[location, call] : s_onceDeferredCalls)
call();
s_deferredCalls.clear();
s_onceDeferredCalls.clear();
}
void TaskManager::runWhenTasksFinished(const std::function<void()> &function) {