logic: reimplemented task system to abort ast visiting

* reimplemented interrupting TaskParseCxx by adding a listener for the MessageInterruptTask and returning a failure status code on update. This cancels the parent sequence task which results in the indexed items not getting inserted into the persistent storage
* removed the capability for interrupting from TaskScheduler
* changed task system to be closer to the standard behavior tree implementation
* changed task system to accommodate the 3 status return types: Running, Success and Failure
* made TaskGroupSequential fail once a member task fails
* made TaskGroupParallel fail once a member task fails
* split TaskParse... into one task for indexing and one task for injecting
* added TaskRunner that handles updating and resetting the managed task
* fixed numbers that are shown as parsed file count in indexing ui
* fixed deadlock that originated from interaction between TaskScheduler and MessageQueue (one thread wanted to destroy a message listener on a task while the other one wanted to send as message as a task)
This commit is contained in:
malte_langkabel
2016-09-07 14:39:34 +02:00
parent cbcf56f7dc
commit 4f302b0d1d
48 changed files with 651 additions and 678 deletions
+29 -143
View File
@@ -32,16 +32,13 @@ public:
int order = 0;
TestTask task(&order, 1);
task.executeTask();
executeTask(task);
TS_ASSERT_EQUALS(3, order);
TS_ASSERT_EQUALS(1, task.enterCallOrder);
TS_ASSERT_EQUALS(2, task.updateCallOrder);
TS_ASSERT_EQUALS(3, task.exitCallOrder);
TS_ASSERT_EQUALS(0, task.interruptCallOrder);
TS_ASSERT_EQUALS(0, task.revertCallOrder);
TS_ASSERT_EQUALS(0, task.abortCallOrder);
}
void test_scheduled_tasks_get_processed_with_callbacks_in_correct_order(void)
@@ -62,34 +59,6 @@ public:
TS_ASSERT_EQUALS(1, task->enterCallOrder);
TS_ASSERT_EQUALS(2, task->updateCallOrder);
TS_ASSERT_EQUALS(3, task->exitCallOrder);
TS_ASSERT_EQUALS(0, task->interruptCallOrder);
TS_ASSERT_EQUALS(0, task->revertCallOrder);
TS_ASSERT_EQUALS(0, task->abortCallOrder);
}
void test_scheduled_tasks_get_interrupted_with_callbacks_in_correct_order(void)
{
TaskScheduler::getInstance()->startSchedulerLoopThreaded();
int order = 0;
std::shared_ptr<TestTask> task = std::make_shared<TestTask>(&order, -1);
Task::dispatch(task);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
TaskScheduler::getInstance()->interruptCurrentTask();
waitForThread();
TaskScheduler::getInstance()->stopSchedulerLoop();
TS_ASSERT_EQUALS(1, task->enterCallOrder);
TS_ASSERT_EQUALS(order - 2, task->updateCallOrder);
TS_ASSERT_EQUALS(order - 1, task->interruptCallOrder);
TS_ASSERT_EQUALS(order, task->exitCallOrder);
TS_ASSERT_EQUALS(0, task->revertCallOrder);
TS_ASSERT_EQUALS(0, task->abortCallOrder);
}
void test_sequential_task_group_to_process_tasks_in_correct_order(void)
@@ -115,24 +84,18 @@ public:
TS_ASSERT_EQUALS(1, task1->enterCallOrder);
TS_ASSERT_EQUALS(2, task1->updateCallOrder);
TS_ASSERT_EQUALS(3, task1->exitCallOrder);
TS_ASSERT_EQUALS(0, task1->interruptCallOrder);
TS_ASSERT_EQUALS(0, task1->revertCallOrder);
TS_ASSERT_EQUALS(0, task1->abortCallOrder);
TS_ASSERT_EQUALS(4, task2->enterCallOrder);
TS_ASSERT_EQUALS(5, task2->updateCallOrder);
TS_ASSERT_EQUALS(6, task2->exitCallOrder);
TS_ASSERT_EQUALS(0, task2->interruptCallOrder);
TS_ASSERT_EQUALS(0, task2->revertCallOrder);
TS_ASSERT_EQUALS(0, task2->abortCallOrder);
}
void test_sequential_task_group_to_interrupt_and_revert_tasks_in_correct_order(void)
void test_sequential_task_group_does_not_evaluate_tasks_after_failure(void)
{
TaskScheduler::getInstance()->startSchedulerLoopThreaded();
int order = 0;
std::shared_ptr<TestTask> task1 = std::make_shared<TestTask>(&order, 1);
std::shared_ptr<TestTask> task1 = std::make_shared<TestTask>(&order, 1, Task::STATE_FAILURE);
std::shared_ptr<TestTask> task2 = std::make_shared<TestTask>(&order, -1);
std::shared_ptr<TaskGroupSequential> taskGroup = std::make_shared<TaskGroupSequential>();
@@ -141,10 +104,6 @@ public:
Task::dispatch(taskGroup);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
TaskScheduler::getInstance()->interruptCurrentTask();
waitForThread();
TaskScheduler::getInstance()->stopSchedulerLoop();
@@ -152,77 +111,10 @@ public:
TS_ASSERT_EQUALS(1, task1->enterCallOrder);
TS_ASSERT_EQUALS(2, task1->updateCallOrder);
TS_ASSERT_EQUALS(3, task1->exitCallOrder);
TS_ASSERT_EQUALS(0, task1->interruptCallOrder);
TS_ASSERT_EQUALS(order - 2, task1->revertCallOrder);
TS_ASSERT_EQUALS(0, task1->abortCallOrder);
TS_ASSERT_EQUALS(4, task2->enterCallOrder);
TS_ASSERT_EQUALS(order - 3, task2->updateCallOrder);
TS_ASSERT_EQUALS(order - 1, task2->interruptCallOrder);
TS_ASSERT_EQUALS(order, task2->exitCallOrder);
TS_ASSERT_EQUALS(0, task2->revertCallOrder);
TS_ASSERT_EQUALS(0, task2->abortCallOrder);
}
void test_sequential_task_group_to_interrupt_and_revert_nested_task_groups_in_correct_order(void)
{
TaskScheduler::getInstance()->startSchedulerLoopThreaded();
int order = 0;
std::shared_ptr<TestTask> task1 = std::make_shared<TestTask>(&order, 1);
std::shared_ptr<TestTask> task2 = std::make_shared<TestTask>(&order, 1);
std::shared_ptr<TestTask> task3 = std::make_shared<TestTask>(&order, -1);
std::shared_ptr<TestTask> task4 = std::make_shared<TestTask>(&order, 1);
std::shared_ptr<TaskGroupSequential> taskGroup1 = std::make_shared<TaskGroupSequential>();
taskGroup1->addTask(task1);
taskGroup1->addTask(task2);
std::shared_ptr<TaskGroupSequential> taskGroup2 = std::make_shared<TaskGroupSequential>();
taskGroup2->addTask(task3);
taskGroup2->addTask(task4);
std::shared_ptr<TaskGroupSequential> taskGroup3 = std::make_shared<TaskGroupSequential>();
taskGroup3->addTask(taskGroup1);
taskGroup3->addTask(taskGroup2);
Task::dispatch(taskGroup3);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
TaskScheduler::getInstance()->interruptCurrentTask();
waitForThread();
TaskScheduler::getInstance()->stopSchedulerLoop();
TS_ASSERT_EQUALS(1, task1->enterCallOrder);
TS_ASSERT_EQUALS(2, task1->updateCallOrder);
TS_ASSERT_EQUALS(3, task1->exitCallOrder);
TS_ASSERT_EQUALS(0, task1->interruptCallOrder);
TS_ASSERT_EQUALS(order - 3, task1->revertCallOrder);
TS_ASSERT_EQUALS(0, task1->abortCallOrder);
TS_ASSERT_EQUALS(4, task2->enterCallOrder);
TS_ASSERT_EQUALS(5, task2->updateCallOrder);
TS_ASSERT_EQUALS(6, task2->exitCallOrder);
TS_ASSERT_EQUALS(0, task2->interruptCallOrder);
TS_ASSERT_EQUALS(order - 4, task2->revertCallOrder);
TS_ASSERT_EQUALS(0, task2->abortCallOrder);
TS_ASSERT_EQUALS(7, task3->enterCallOrder);
TS_ASSERT_EQUALS(order - 5, task3->updateCallOrder);
TS_ASSERT_EQUALS(order - 2, task3->interruptCallOrder);
TS_ASSERT_EQUALS(order - 1, task3->exitCallOrder);
TS_ASSERT_EQUALS(0, task3->revertCallOrder);
TS_ASSERT_EQUALS(0, task3->abortCallOrder);
TS_ASSERT_EQUALS(0, task4->enterCallOrder);
TS_ASSERT_EQUALS(0, task4->updateCallOrder);
TS_ASSERT_EQUALS(0, task4->exitCallOrder);
TS_ASSERT_EQUALS(0, task4->interruptCallOrder);
TS_ASSERT_EQUALS(0, task4->revertCallOrder);
TS_ASSERT_EQUALS(order, task4->abortCallOrder);
TS_ASSERT_EQUALS(0, task2->enterCallOrder);
TS_ASSERT_EQUALS(0, task2->updateCallOrder);
TS_ASSERT_EQUALS(0, task2->exitCallOrder);
}
void test_task_scheduling_within_task_processing()
@@ -243,39 +135,44 @@ public:
TS_ASSERT_EQUALS(1, task->enterCallOrder);
TS_ASSERT_EQUALS(2, task->updateCallOrder);
TS_ASSERT_EQUALS(3, task->exitCallOrder);
TS_ASSERT_EQUALS(0, task->interruptCallOrder);
TS_ASSERT_EQUALS(0, task->revertCallOrder);
TS_ASSERT_EQUALS(4, task->subTask->enterCallOrder);
TS_ASSERT_EQUALS(5, task->subTask->updateCallOrder);
TS_ASSERT_EQUALS(6, task->subTask->exitCallOrder);
TS_ASSERT_EQUALS(0, task->subTask->interruptCallOrder);
TS_ASSERT_EQUALS(0, task->subTask->revertCallOrder);
}
private:
void executeTask(Task& task)
{
while (true)
{
if (task.update() != Task::STATE_RUNNING)
{
return;
}
}
}
class TestTask: public Task
{
public:
TestTask(int* orderCountPtr, int updateCount)
TestTask(int* orderCountPtr, int updateCount, TaskState returnState = STATE_SUCCESS)
: orderCount(*orderCountPtr)
, updateCount(updateCount)
, returnState(returnState)
, enterCallOrder(0)
, updateCallOrder(0)
, exitCallOrder(0)
, interruptCallOrder(0)
, revertCallOrder(0)
, abortCallOrder(0)
, resetCallOrder(0)
{
}
virtual void enter()
virtual void doEnter()
{
enterCallOrder = ++orderCount;
}
virtual TaskState update()
virtual TaskState doUpdate()
{
updateCallOrder = ++orderCount;
@@ -291,38 +188,27 @@ private:
return Task::STATE_RUNNING;
}
return Task::STATE_FINISHED;
return returnState;
}
virtual void exit()
virtual void doExit()
{
exitCallOrder = ++orderCount;
}
virtual void interrupt()
virtual void doReset()
{
interruptCallOrder = ++orderCount;
}
virtual void revert()
{
revertCallOrder = ++orderCount;
}
virtual void abort()
{
abortCallOrder = ++orderCount;
resetCallOrder = ++orderCount;
}
int& orderCount;
int updateCount;
TaskState returnState;
int enterCallOrder;
int updateCallOrder;
int exitCallOrder;
int interruptCallOrder;
int revertCallOrder;
int abortCallOrder;
int resetCallOrder;
};
class TestTaskDispatch: public TestTask
@@ -333,12 +219,12 @@ private:
{
}
virtual TaskState update()
virtual TaskState doUpdate()
{
subTask = std::make_shared<TestTask>(&orderCount, 1);
Task::dispatch(subTask);
return TestTask::update();
return TestTask::doUpdate();
}
std::shared_ptr<TestTask> subTask;