Files
ObsidianDragon/src/util/async_task_manager.cpp
DanS 9edab31728 Refactor app services and stabilize refresh/UI flows
- Add refresh scheduler and network refresh service boundaries for typed
  refresh results, ordered RPC collectors, applicators, and price parsing.
- Add daemon lifecycle and wallet security workflow helpers while preserving
  App-owned command RPC, decrypt, cancellation, and UI handoff behavior.
- Split balance, console, mining, amount formatting, and async task logic into
  focused modules with expanded Phase 4 test coverage.
- Fix market price loading by triggering price refresh immediately, avoiding
  queue-pressure drops, tracking loading/error state, and adding translations.
- Polish send, explorer, peers, settings, theme/schema, and related tab UI.
- Replace checked-in generated language headers with build-generated resources.
- Document the cleanup audit, UI static-state guidance, and architecture updates.
2026-04-29 12:47:57 -05:00

119 lines
2.9 KiB
C++

#include "async_task_manager.h"
#include "logger.h"
#include <exception>
#include <utility>
namespace dragonx {
namespace util {
AsyncTaskManager::~AsyncTaskManager()
{
cancelAll();
joinAll();
}
void AsyncTaskManager::submit(std::string name, Task task)
{
if (!task) return;
reapCompleted();
join(name);
auto cancelled = std::make_shared<std::atomic<bool>>(false);
auto done = std::make_shared<std::atomic<bool>>(false);
Token token(cancelled);
std::string taskName = name;
std::thread worker([taskName, token, done, task = std::move(task)]() mutable {
try {
task(token);
} catch (const std::exception& e) {
DEBUG_LOGF("[AsyncTask:%s] failed: %s\n", taskName.c_str(), e.what());
} catch (...) {
DEBUG_LOGF("[AsyncTask:%s] failed with unknown exception\n", taskName.c_str());
}
done->store(true, std::memory_order_release);
});
std::lock_guard<std::mutex> lock(mutex_);
tasks_.push_back({std::move(name), std::move(cancelled), std::move(done), std::move(worker)});
}
void AsyncTaskManager::cancelAll()
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto& task : tasks_) {
task.cancelled->store(true, std::memory_order_relaxed);
}
}
void AsyncTaskManager::join(const std::string& name)
{
std::vector<TaskEntry> toJoin;
{
std::lock_guard<std::mutex> lock(mutex_);
auto it = tasks_.begin();
while (it != tasks_.end()) {
if (it->name == name) {
toJoin.push_back(std::move(*it));
it = tasks_.erase(it);
} else {
++it;
}
}
}
for (auto& task : toJoin) {
if (task.worker.joinable()) task.worker.join();
}
}
void AsyncTaskManager::joinAll()
{
std::vector<TaskEntry> toJoin;
{
std::lock_guard<std::mutex> lock(mutex_);
toJoin.swap(tasks_);
}
for (auto& task : toJoin) {
if (task.worker.joinable()) task.worker.join();
}
}
void AsyncTaskManager::reapCompleted()
{
std::vector<TaskEntry> toJoin;
{
std::lock_guard<std::mutex> lock(mutex_);
auto it = tasks_.begin();
while (it != tasks_.end()) {
if (it->done->load(std::memory_order_acquire)) {
toJoin.push_back(std::move(*it));
it = tasks_.erase(it);
} else {
++it;
}
}
}
for (auto& task : toJoin) {
if (task.worker.joinable()) task.worker.join();
}
}
bool AsyncTaskManager::isRunning(const std::string& name) const
{
std::lock_guard<std::mutex> lock(mutex_);
for (const auto& task : tasks_) {
if (task.name == name && !task.done->load(std::memory_order_acquire)) {
return true;
}
}
return false;
}
} // namespace util
} // namespace dragonx