From 6e342fa87cf2a84e134041c37ac353d5da868220 Mon Sep 17 00:00:00 2001 From: malte_langkabel Date: Wed, 12 Apr 2017 10:46:56 +0200 Subject: [PATCH] logic: terminating all running tasks before closing the application (issue #343) --- src/lib/data/parser/TaskParseWrapper.cpp | 5 ++ src/lib/data/parser/TaskParseWrapper.h | 1 + src/lib/utility/ScopedFunctor.cpp | 5 ++ src/lib/utility/ScopedFunctor.h | 1 + src/lib/utility/scheduling/Task.cpp | 5 ++ src/lib/utility/scheduling/Task.h | 1 + src/lib/utility/scheduling/TaskDecorator.cpp | 5 ++ src/lib/utility/scheduling/TaskDecorator.h | 4 ++ .../scheduling/TaskDecoratorRepeat.cpp | 5 ++ .../utility/scheduling/TaskDecoratorRepeat.h | 1 + src/lib/utility/scheduling/TaskGroup.cpp | 7 ++- src/lib/utility/scheduling/TaskGroup.h | 4 ++ .../utility/scheduling/TaskGroupParallel.cpp | 13 ++++++ .../utility/scheduling/TaskGroupParallel.h | 1 + .../utility/scheduling/TaskGroupSelector.cpp | 8 ++++ .../utility/scheduling/TaskGroupSelector.h | 1 + .../utility/scheduling/TaskGroupSequence.cpp | 8 ++++ .../utility/scheduling/TaskGroupSequence.h | 1 + src/lib/utility/scheduling/TaskRunner.cpp | 9 ++++ src/lib/utility/scheduling/TaskRunner.h | 3 +- src/lib/utility/scheduling/TaskScheduler.cpp | 1 + src/lib_cxx/project/SourceGroupCxx.cpp | 17 ++++--- src/lib_java/project/SourceGroupJava.cpp | 46 ++++++++++++------- 23 files changed, 127 insertions(+), 25 deletions(-) diff --git a/src/lib/data/parser/TaskParseWrapper.cpp b/src/lib/data/parser/TaskParseWrapper.cpp index 407367f0..e8cbdb59 100644 --- a/src/lib/data/parser/TaskParseWrapper.cpp +++ b/src/lib/data/parser/TaskParseWrapper.cpp @@ -54,3 +54,8 @@ void TaskParseWrapper::doReset(std::shared_ptr blackboard) { m_taskRunner->reset(); } + +void TaskParseWrapper::doTerminate() +{ + m_taskRunner->terminate(); +} diff --git a/src/lib/data/parser/TaskParseWrapper.h b/src/lib/data/parser/TaskParseWrapper.h index 70691c6c..9815c21a 100644 --- a/src/lib/data/parser/TaskParseWrapper.h +++ b/src/lib/data/parser/TaskParseWrapper.h @@ -28,6 +28,7 @@ private: virtual TaskState doUpdate(std::shared_ptr blackboard); virtual void doExit(std::shared_ptr blackboard); virtual void doReset(std::shared_ptr blackboard); + virtual void doTerminate(); PersistentStorage* m_storage; diff --git a/src/lib/utility/ScopedFunctor.cpp b/src/lib/utility/ScopedFunctor.cpp index b51c2170..23d7496b 100644 --- a/src/lib/utility/ScopedFunctor.cpp +++ b/src/lib/utility/ScopedFunctor.cpp @@ -1,5 +1,10 @@ #include "utility/ScopedFunctor.h" +ScopedFunctor::ScopedFunctor() + : m_onDestroy([](){}) +{ +} + ScopedFunctor::ScopedFunctor(std::function onDestroy) : m_onDestroy(onDestroy) { diff --git a/src/lib/utility/ScopedFunctor.h b/src/lib/utility/ScopedFunctor.h index 1df94cf1..2a00dabd 100644 --- a/src/lib/utility/ScopedFunctor.h +++ b/src/lib/utility/ScopedFunctor.h @@ -6,6 +6,7 @@ class ScopedFunctor { public: + ScopedFunctor(); ScopedFunctor(std::function onDestroy); ~ScopedFunctor(); diff --git a/src/lib/utility/scheduling/Task.cpp b/src/lib/utility/scheduling/Task.cpp index c2b9d677..236ec262 100644 --- a/src/lib/utility/scheduling/Task.cpp +++ b/src/lib/utility/scheduling/Task.cpp @@ -48,3 +48,8 @@ void Task::reset(std::shared_ptr blackboard) m_enterCalled = false; m_exitCalled = false; } + +void Task::terminate() +{ +} + diff --git a/src/lib/utility/scheduling/Task.h b/src/lib/utility/scheduling/Task.h index 01c86b45..69e9124b 100644 --- a/src/lib/utility/scheduling/Task.h +++ b/src/lib/utility/scheduling/Task.h @@ -23,6 +23,7 @@ public: TaskState update(std::shared_ptr blackboard); void reset(std::shared_ptr blackboard); + virtual void terminate(); // caution: this should only be called just before quitting the app. private: virtual void doEnter(std::shared_ptr blackboard) = 0; diff --git a/src/lib/utility/scheduling/TaskDecorator.cpp b/src/lib/utility/scheduling/TaskDecorator.cpp index 56e24bb5..f6070741 100644 --- a/src/lib/utility/scheduling/TaskDecorator.cpp +++ b/src/lib/utility/scheduling/TaskDecorator.cpp @@ -13,3 +13,8 @@ std::shared_ptr TaskDecorator::addChildTask(std::shared_ptr setTask(child); return shared_from_this(); } + +void TaskDecorator::terminate() +{ + doTerminate(); +} diff --git a/src/lib/utility/scheduling/TaskDecorator.h b/src/lib/utility/scheduling/TaskDecorator.h index cabb3929..c8b010cb 100644 --- a/src/lib/utility/scheduling/TaskDecorator.h +++ b/src/lib/utility/scheduling/TaskDecorator.h @@ -15,6 +15,10 @@ public: std::shared_ptr addChildTask(std::shared_ptr child); virtual void setTask(std::shared_ptr task) = 0; + virtual void terminate(); + +private: + virtual void doTerminate() = 0; }; #endif // TASK_DECORATOR_H diff --git a/src/lib/utility/scheduling/TaskDecoratorRepeat.cpp b/src/lib/utility/scheduling/TaskDecoratorRepeat.cpp index 88404791..b165be62 100644 --- a/src/lib/utility/scheduling/TaskDecoratorRepeat.cpp +++ b/src/lib/utility/scheduling/TaskDecoratorRepeat.cpp @@ -48,3 +48,8 @@ void TaskDecoratorRepeat::doReset(std::shared_ptr blackboard) { m_taskRunner->reset(); } + +void TaskDecoratorRepeat::doTerminate() +{ + m_taskRunner->terminate(); +} diff --git a/src/lib/utility/scheduling/TaskDecoratorRepeat.h b/src/lib/utility/scheduling/TaskDecoratorRepeat.h index ceeb9374..7fdc7ba8 100644 --- a/src/lib/utility/scheduling/TaskDecoratorRepeat.h +++ b/src/lib/utility/scheduling/TaskDecoratorRepeat.h @@ -24,6 +24,7 @@ private: virtual TaskState doUpdate(std::shared_ptr blackboard); virtual void doExit(std::shared_ptr blackboard); virtual void doReset(std::shared_ptr blackboard); + virtual void doTerminate(); std::shared_ptr m_taskRunner; const ConditionType m_condition; diff --git a/src/lib/utility/scheduling/TaskGroup.cpp b/src/lib/utility/scheduling/TaskGroup.cpp index 77e2c9bc..82828466 100644 --- a/src/lib/utility/scheduling/TaskGroup.cpp +++ b/src/lib/utility/scheduling/TaskGroup.cpp @@ -27,4 +27,9 @@ std::shared_ptr TaskGroup::addChildTasks(std::shared_ptr child1 addTask(child2); addTask(child3); return shared_from_this(); -} \ No newline at end of file +} + +void TaskGroup::terminate() +{ + doTerminate(); +} diff --git a/src/lib/utility/scheduling/TaskGroup.h b/src/lib/utility/scheduling/TaskGroup.h index 70ee3fa3..776a8b19 100644 --- a/src/lib/utility/scheduling/TaskGroup.h +++ b/src/lib/utility/scheduling/TaskGroup.h @@ -18,6 +18,10 @@ public: std::shared_ptr addChildTasks(std::shared_ptr child1, std::shared_ptr child2, std::shared_ptr child3); virtual void addTask(std::shared_ptr task) = 0; + virtual void terminate(); + +private: + virtual void doTerminate() = 0; }; diff --git a/src/lib/utility/scheduling/TaskGroupParallel.cpp b/src/lib/utility/scheduling/TaskGroupParallel.cpp index 599b8c2f..73c6b204 100644 --- a/src/lib/utility/scheduling/TaskGroupParallel.cpp +++ b/src/lib/utility/scheduling/TaskGroupParallel.cpp @@ -73,6 +73,19 @@ void TaskGroupParallel::doReset(std::shared_ptr blackboard) } } +void TaskGroupParallel::doTerminate() +{ + for (size_t i = 0; i < m_tasks.size(); i++) + { + m_tasks[i]->taskRunner->terminate(); + if (m_tasks[i]->thread) + { + m_tasks[i]->thread->detach(); + m_tasks[i]->thread.reset(); + } + } +} + void TaskGroupParallel::processTaskThreaded(std::shared_ptr taskInfo, std::shared_ptr blackboard) { ScopedFunctor functor([&](){ diff --git a/src/lib/utility/scheduling/TaskGroupParallel.h b/src/lib/utility/scheduling/TaskGroupParallel.h index 4d03cf0b..1f272098 100644 --- a/src/lib/utility/scheduling/TaskGroupParallel.h +++ b/src/lib/utility/scheduling/TaskGroupParallel.h @@ -33,6 +33,7 @@ private: virtual TaskState doUpdate(std::shared_ptr blackboard); virtual void doExit(std::shared_ptr blackboard); virtual void doReset(std::shared_ptr blackboard); + virtual void doTerminate(); void processTaskThreaded(std::shared_ptr taskInfo, std::shared_ptr blackboard); int getActveTaskCount() const; diff --git a/src/lib/utility/scheduling/TaskGroupSelector.cpp b/src/lib/utility/scheduling/TaskGroupSelector.cpp index ecdc5cca..8fdd292f 100644 --- a/src/lib/utility/scheduling/TaskGroupSelector.cpp +++ b/src/lib/utility/scheduling/TaskGroupSelector.cpp @@ -54,3 +54,11 @@ void TaskGroupSelector::doReset(std::shared_ptr blackboard) m_taskRunners[i]->reset(); } } + +void TaskGroupSelector::doTerminate() +{ + for (size_t i = 0; i < m_taskRunners.size(); i++) + { + m_taskRunners[i]->terminate(); + } +} diff --git a/src/lib/utility/scheduling/TaskGroupSelector.h b/src/lib/utility/scheduling/TaskGroupSelector.h index 65f8a943..291f63e8 100644 --- a/src/lib/utility/scheduling/TaskGroupSelector.h +++ b/src/lib/utility/scheduling/TaskGroupSelector.h @@ -18,6 +18,7 @@ private: virtual TaskState doUpdate(std::shared_ptr blackboard); virtual void doExit(std::shared_ptr blackboard); virtual void doReset(std::shared_ptr blackboard); + virtual void doTerminate(); std::vector> m_taskRunners; int m_taskIndex; diff --git a/src/lib/utility/scheduling/TaskGroupSequence.cpp b/src/lib/utility/scheduling/TaskGroupSequence.cpp index caf3cbaf..f406e49c 100644 --- a/src/lib/utility/scheduling/TaskGroupSequence.cpp +++ b/src/lib/utility/scheduling/TaskGroupSequence.cpp @@ -54,3 +54,11 @@ void TaskGroupSequence::doReset(std::shared_ptr blackboard) m_taskRunners[i]->reset(); } } + +void TaskGroupSequence::doTerminate() +{ + for (size_t i = 0; i < m_taskRunners.size(); i++) + { + m_taskRunners[i]->terminate(); + } +} diff --git a/src/lib/utility/scheduling/TaskGroupSequence.h b/src/lib/utility/scheduling/TaskGroupSequence.h index 4085014a..7701cae4 100644 --- a/src/lib/utility/scheduling/TaskGroupSequence.h +++ b/src/lib/utility/scheduling/TaskGroupSequence.h @@ -18,6 +18,7 @@ private: virtual TaskState doUpdate(std::shared_ptr blackboard); virtual void doExit(std::shared_ptr blackboard); virtual void doReset(std::shared_ptr blackboard); + virtual void doTerminate(); std::vector> m_taskRunners; int m_taskIndex; diff --git a/src/lib/utility/scheduling/TaskRunner.cpp b/src/lib/utility/scheduling/TaskRunner.cpp index 1135c262..341bb287 100644 --- a/src/lib/utility/scheduling/TaskRunner.cpp +++ b/src/lib/utility/scheduling/TaskRunner.cpp @@ -26,4 +26,13 @@ void TaskRunner::reset() m_reset = true; } +void TaskRunner::terminate() +{ + if (m_task) + { + m_task->terminate(); + } +} + + diff --git a/src/lib/utility/scheduling/TaskRunner.h b/src/lib/utility/scheduling/TaskRunner.h index c6faa858..4aa358be 100644 --- a/src/lib/utility/scheduling/TaskRunner.h +++ b/src/lib/utility/scheduling/TaskRunner.h @@ -13,10 +13,11 @@ public: Task::TaskState update(std::shared_ptr blackboard); void reset(); + void terminate(); // caution: this should only be called just before quitting the app. private: std::shared_ptr m_task; bool m_reset; }; -#endif // TASK_H +#endif // TASK_RUNNER_H diff --git a/src/lib/utility/scheduling/TaskScheduler.cpp b/src/lib/utility/scheduling/TaskScheduler.cpp index b296d382..e4561d77 100644 --- a/src/lib/utility/scheduling/TaskScheduler.cpp +++ b/src/lib/utility/scheduling/TaskScheduler.cpp @@ -161,6 +161,7 @@ void TaskScheduler::processTasks() if (!m_loopIsRunning) { + runner->terminate(); break; } } diff --git a/src/lib_cxx/project/SourceGroupCxx.cpp b/src/lib_cxx/project/SourceGroupCxx.cpp index 4d4169cd..8a105e26 100644 --- a/src/lib_cxx/project/SourceGroupCxx.cpp +++ b/src/lib_cxx/project/SourceGroupCxx.cpp @@ -35,14 +35,17 @@ bool SourceGroupCxx::prepareRefresh() { MessageStatus("Can't refresh project").dispatch(); - if (Application::getInstance()->hasGUI()) + if (std::shared_ptr application = Application::getInstance()) { - std::vector options; - options.push_back("Ok"); - Application::getInstance()->handleDialog( - "Can't refresh. The compilation database of the project does not exist anymore: " + cdbPath.str(), - options - ); + if (application->hasGUI()) + { + std::vector options; + options.push_back("Ok"); + application->handleDialog( + "Can't refresh. The compilation database of the project does not exist anymore: " + cdbPath.str(), + options + ); + } } return false; } diff --git a/src/lib_java/project/SourceGroupJava.cpp b/src/lib_java/project/SourceGroupJava.cpp index 643a8b8f..9753321e 100644 --- a/src/lib_java/project/SourceGroupJava.cpp +++ b/src/lib_java/project/SourceGroupJava.cpp @@ -51,18 +51,20 @@ void SourceGroupJava::fetchAllSourceFilePaths() std::vector sourcePaths; if (m_settings->getAbsoluteMavenProjectFilePath().exists()) { - if (Application::getInstance()->hasGUI()) + std::shared_ptr application = Application::getInstance(); + + if (application && application->hasGUI()) { - Application::getInstance()->getDialogView()->showStatusDialog("Preparing Project", "Maven\nFetching Source Directories"); + application->getDialogView()->showStatusDialog("Preparing Project", "Maven\nFetching Source Directories"); } const FilePath mavenPath(ApplicationSettings::getInstance()->getMavenPath()); const FilePath projectRootPath = m_settings->getAbsoluteMavenProjectFilePath().parentDirectory(); sourcePaths = utility::mavenGetAllDirectoriesFromEffectivePom(mavenPath, projectRootPath, m_settings->getShouldIndexMavenTests()); - if (Application::getInstance()->hasGUI()) + if (application && application->hasGUI()) { - Application::getInstance()->getDialogView()->hideStatusDialog(); + application->getDialogView()->hideStatusDialog(); } } else @@ -159,23 +161,29 @@ bool SourceGroupJava::prepareJavaEnvironment() bool SourceGroupJava::prepareMavenData() { - if (m_settings->getAbsoluteMavenProjectFilePath().exists()) + if (m_settings && m_settings->getAbsoluteMavenProjectFilePath().exists()) { const FilePath mavenPath = ApplicationSettings::getInstance()->getMavenPath(); const FilePath projectRootPath = m_settings->getAbsoluteMavenProjectFilePath().parentDirectory(); - if (Application::getInstance()->hasGUI()) + ScopedFunctor dialogHider; + + std::shared_ptr application = Application::getInstance(); + + if (application && application->hasGUI()) { - ScopedFunctor dialogHider([](){ + // this makes sure to hide the dialog when leaving this method. + dialogHider = ScopedFunctor([](){ Application::getInstance()->getDialogView()->hideStatusDialog(); }); - Application::getInstance()->getDialogView()->showStatusDialog("Preparing Project", "Maven\nGenerating Source Files"); - bool success = utility::mavenGenerateSources( - mavenPath, projectRootPath - ); + } - if (!success) + bool success = utility::mavenGenerateSources(mavenPath, projectRootPath); + + if (!success) + { + if (application && application->hasGUI()) { const std::string dialogMessage = "Sourcetrail was unable to locate Maven on this machine.\n" @@ -184,11 +192,15 @@ bool SourceGroupJava::prepareMavenData() MessageStatus(dialogMessage, true, false).dispatch(); Application::getInstance()->handleDialog(dialogMessage); - return false; } + return false; + } + if (application && application->hasGUI()) + { Application::getInstance()->getDialogView()->showStatusDialog("Preparing Project", "Maven\nExporting Dependencies"); } + utility::mavenCopyDependencies( mavenPath, projectRootPath, m_settings->getAbsoluteMavenDependenciesDirectory() ); @@ -235,11 +247,13 @@ std::vector SourceGroupJava::getClassPath() std::set SourceGroupJava::fetchRootDirectories() { - if (Application::getInstance()->hasGUI()) + if (std::shared_ptr application = Application::getInstance()) { - Application::getInstance()->getDialogView()->showStatusDialog("Preparing Project", "Gathering Root\nDirectories"); + if (application->hasGUI()) + { + application->getDialogView()->showStatusDialog("Preparing Project", "Gathering Root\nDirectories"); + } } - std::set rootDirectories; std::shared_ptr javaEnvironment = JavaEnvironmentFactory::getInstance()->createEnvironment();