From 3915e03ca0e0fc6694cb5563f4ca0cad77d9f2be Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 23 Feb 2020 19:07:18 +0100 Subject: [PATCH] AsyncDeleter: Have an own queue for just the delete tasks. This fixes exiting the application. --- src/utils/AsyncExecutor.cpp | 57 +++++++++++++++++++++++-------------- src/utils/AsyncExecutor.h | 30 ++++++++++++------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/utils/AsyncExecutor.cpp b/src/utils/AsyncExecutor.cpp index 708f264..a27f673 100644 --- a/src/utils/AsyncExecutor.cpp +++ b/src/utils/AsyncExecutor.cpp @@ -3,42 +3,57 @@ AsyncExecutor * AsyncExecutor::instance = NULL; -void AsyncExecutor::pushForDelete(GuiElement * ptr) { - execute([ptr] {delete ptr;}); +void AsyncExecutor::pushForDeleteInternal(GuiElement * ptr) { + deleteListMutex.lock(); + deleteList.push(ptr); + deleteListMutex.unlock(); } AsyncExecutor::AsyncExecutor() { thread = new std::thread([&]() { while(!exitThread) { - instance->mutex.lock(); - auto it = instance->elements.begin(); - while (it != instance->elements.end()) { + mutex.lock(); + bool emptyList = elements.empty(); + auto it = elements.begin(); + while (it != elements.end()) { auto future = it; auto status = future->wait_for(std::chrono::seconds(0)); if (status == std::future_status::ready) { - it = instance->elements.erase(it); + it = elements.erase(it); } else { ++it; } } - instance->mutex.unlock(); + if(!emptyList && elements.empty()){ + DEBUG_FUNCTION_LINE("All tasks are done\n"); + } + mutex.unlock(); + deleteListMutex.lock(); + while(!deleteList.empty()) { + GuiElement * ptr = deleteList.front(); + deleteList.pop(); + delete ptr; + } + deleteListMutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(16)); DCFlushRange((void*)&exitThread, sizeof(exitThread)); } }); - - thread->detach(); } -void AsyncExecutor::execute(std::function func) { - if(!instance) { - instance = new AsyncExecutor(); - } - - while(instance->elements.size() > 25) { - std::this_thread::sleep_for(std::chrono::milliseconds(16)); - } - - instance->mutex.lock(); - instance->elements.push_back(std::async(std::launch::async,func)); - instance->mutex.unlock(); +AsyncExecutor::~AsyncExecutor() { + exitThread = true; + DCFlushRange((void*)&exitThread, sizeof(exitThread)); + thread->join(); +} + +void AsyncExecutor::executeInternal(std::function func) { + if(elements.size() > 10) { + DEBUG_FUNCTION_LINE("Warning, many tasks running currently\n"); + //std::this_thread::sleep_for(std::chrono::milliseconds(16)); + } + DEBUG_FUNCTION_LINE("Add new task\n"); + mutex.lock(); + elements.push_back(std::async(std::launch::async,func)); + mutex.unlock(); } diff --git a/src/utils/AsyncExecutor.h b/src/utils/AsyncExecutor.h index 845f6c9..8994c97 100644 --- a/src/utils/AsyncExecutor.h +++ b/src/utils/AsyncExecutor.h @@ -1,18 +1,27 @@ -#ifndef ___ASYNCEXECUTER_H_ -#define ___ASYNCEXECUTER_H_ - +#pragma once #include #include #include +#include #include #include #include "utils/logger.h" class AsyncExecutor { public: - static void pushForDelete(GuiElement * element); - static void execute(std::function func); + static void pushForDelete(GuiElement * element) { + if(!instance) { + instance = new AsyncExecutor(); + } + instance->pushForDeleteInternal(element); + } + static void execute(std::function func) { + if(!instance) { + instance = new AsyncExecutor(); + } + instance->executeInternal(func); + } static void destroyInstance() { if(instance) { @@ -25,16 +34,17 @@ private: static AsyncExecutor *instance; AsyncExecutor(); + ~AsyncExecutor(); - ~AsyncExecutor() { - exitThread = true; - DCFlushRange((void*)&exitThread, sizeof(exitThread)); - } + void pushForDeleteInternal(GuiElement * element); + void executeInternal(std::function func); std::recursive_mutex mutex; std::thread * thread; volatile bool exitThread = false; std::vector> elements; + + std::recursive_mutex deleteListMutex; + std::queue deleteList; }; -#endif