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:
@@ -192,6 +192,10 @@ add_files(
|
||||
data/StorageStats.h
|
||||
data/TaskCleanStorage.cpp
|
||||
data/TaskCleanStorage.h
|
||||
data/TaskInjectStorage.cpp
|
||||
data/TaskInjectStorage.h
|
||||
data/TaskRepeatWhileUnparsedSourceFilesAvailable.cpp
|
||||
data/TaskRepeatWhileUnparsedSourceFilesAvailable.h
|
||||
|
||||
settings/ApplicationSettings.cpp
|
||||
settings/ApplicationSettings.h
|
||||
@@ -312,6 +316,8 @@ add_files(
|
||||
utility/scheduling/TaskGroupSequential.h
|
||||
utility/scheduling/TaskLambda.cpp
|
||||
utility/scheduling/TaskLambda.h
|
||||
utility/scheduling/TaskRunner.cpp
|
||||
utility/scheduling/TaskRunner.h
|
||||
utility/scheduling/TaskScheduler.cpp
|
||||
utility/scheduling/TaskScheduler.h
|
||||
|
||||
|
||||
@@ -54,13 +54,11 @@ bool CxxProject::prepareRefresh()
|
||||
}
|
||||
|
||||
std::shared_ptr<Task> CxxProject::createIndexerTask(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister)
|
||||
{
|
||||
return std::make_shared<TaskParseCxx>(
|
||||
storage,
|
||||
storageMutex,
|
||||
fileRegister,
|
||||
getParserArguments(),
|
||||
getDialogView()
|
||||
|
||||
@@ -26,8 +26,7 @@ private:
|
||||
virtual bool prepareRefresh();
|
||||
|
||||
virtual std::shared_ptr<Task> createIndexerTask(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister);
|
||||
|
||||
virtual void updateFileManager(FileManager& fileManager);
|
||||
|
||||
@@ -76,8 +76,7 @@ bool JavaProject::prepareIndexing()
|
||||
}
|
||||
|
||||
std::shared_ptr<Task> JavaProject::createIndexerTask(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister)
|
||||
{
|
||||
Parser::Arguments arguments;
|
||||
@@ -100,7 +99,6 @@ std::shared_ptr<Task> JavaProject::createIndexerTask(
|
||||
|
||||
return std::make_shared<TaskParseJava>(
|
||||
storage,
|
||||
storageMutex,
|
||||
fileRegister,
|
||||
arguments,
|
||||
getDialogView()
|
||||
|
||||
@@ -26,8 +26,7 @@ private:
|
||||
virtual bool prepareIndexing();
|
||||
|
||||
virtual std::shared_ptr<Task> createIndexerTask(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister);
|
||||
|
||||
virtual void updateFileManager(FileManager& fileManager);
|
||||
|
||||
+12
-1
@@ -6,6 +6,8 @@
|
||||
#include "data/parser/java/TaskParseJava.h"
|
||||
#include "data/PersistentStorage.h"
|
||||
#include "data/TaskCleanStorage.h"
|
||||
#include "data/TaskInjectStorage.h"
|
||||
#include "data/TaskRepeatWhileUnparsedSourceFilesAvailable.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
#include "settings/ProjectSettings.h"
|
||||
|
||||
@@ -327,7 +329,16 @@ bool Project::buildIndex(bool forceRefresh)
|
||||
|
||||
for (int i = 0; i < indexerThreadCount; i++)
|
||||
{
|
||||
taskParallelIndexing->addTask(createIndexerTask(m_storage.get(), storageMutex, fileRegister));
|
||||
std::shared_ptr<TaskRepeatWhileUnparsedSourceFilesAvailable> taskRepeat = std::make_shared<TaskRepeatWhileUnparsedSourceFilesAvailable>(fileRegister);
|
||||
taskParallelIndexing->addTask(taskRepeat);
|
||||
|
||||
std::shared_ptr<TaskGroupSequential> taskRepeatSequential = std::make_shared<TaskGroupSequential>();
|
||||
taskRepeat->setTask(taskRepeatSequential);
|
||||
|
||||
std::shared_ptr<IntermediateStorage> intermediateStorage = std::make_shared<IntermediateStorage>();
|
||||
|
||||
taskRepeatSequential->addTask(createIndexerTask(intermediateStorage, fileRegister));
|
||||
taskRepeatSequential->addTask(std::make_shared<TaskInjectStorage>(intermediateStorage, m_storage));
|
||||
}
|
||||
|
||||
Task::dispatch(taskSequential);
|
||||
|
||||
+2
-2
@@ -12,6 +12,7 @@
|
||||
class DialogView;
|
||||
class FileRegister;
|
||||
class PersistentStorage;
|
||||
class IntermediateStorage;
|
||||
class ProjectSettings;
|
||||
class StorageAccessProxy;
|
||||
class Task;
|
||||
@@ -62,8 +63,7 @@ private:
|
||||
virtual bool prepareIndexing();
|
||||
virtual bool prepareRefresh();
|
||||
virtual std::shared_ptr<Task> createIndexerTask(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister) = 0;
|
||||
virtual void updateFileManager(FileManager& fileManager) = 0;
|
||||
|
||||
|
||||
@@ -12,6 +12,23 @@ IntermediateStorage::~IntermediateStorage()
|
||||
{
|
||||
}
|
||||
|
||||
void IntermediateStorage::clear()
|
||||
{
|
||||
m_fileNamesToIds.clear();
|
||||
m_fileIdsToData.clear();
|
||||
m_nodeNamesToIds.clear();
|
||||
m_nodeIdsToData.clear();
|
||||
m_edgeNamesToIds.clear();
|
||||
m_edgeIdsToData.clear();
|
||||
m_localSymbolNamesToIds.clear();
|
||||
m_localSymbolIdsToData.clear();
|
||||
m_sourceLocations.clear();
|
||||
m_componentAccesses.clear();
|
||||
m_commentLocations.clear();
|
||||
m_errors.clear();
|
||||
m_nextId = 1;
|
||||
}
|
||||
|
||||
Id IntermediateStorage::addFile(const std::string& name, const std::string& filePath, const std::string& modificationTime)
|
||||
{
|
||||
std::shared_ptr<StorageFile> file = std::make_shared<StorageFile>(0, name, filePath, modificationTime);
|
||||
|
||||
@@ -14,6 +14,8 @@ public:
|
||||
IntermediateStorage();
|
||||
virtual ~IntermediateStorage();
|
||||
|
||||
void clear();
|
||||
|
||||
virtual Id addFile(const std::string& name, const std::string& filePath, const std::string& modificationTime);
|
||||
virtual Id addNode(int type, const std::string& serializedName, int definitionType);
|
||||
virtual Id addEdge(int type, Id sourceId, Id targetId);
|
||||
@@ -56,8 +58,6 @@ private:
|
||||
std::vector<StorageCommentLocation> m_commentLocations;
|
||||
std::vector<StorageError> m_errors;
|
||||
|
||||
std::unordered_map<Id, Id> m_nodeIdsToMemberEdgeIds;
|
||||
|
||||
Id m_nextId;
|
||||
};
|
||||
|
||||
|
||||
+12
-11
@@ -15,20 +15,11 @@ Storage::~Storage()
|
||||
{
|
||||
}
|
||||
|
||||
void Storage::startInjection()
|
||||
{
|
||||
// may be implemented in derived
|
||||
}
|
||||
|
||||
void Storage::finishInjection()
|
||||
{
|
||||
// may be implemented in derived
|
||||
}
|
||||
|
||||
void Storage::inject(Storage* injected)
|
||||
{
|
||||
TRACE();
|
||||
std::lock_guard<std::mutex> lock(m_dataMutex);
|
||||
|
||||
TRACE();
|
||||
startInjection();
|
||||
|
||||
std::unordered_map<Id, Id> injectedIdToOwnId;
|
||||
@@ -180,3 +171,13 @@ void Storage::inject(Storage* injected)
|
||||
|
||||
finishInjection();
|
||||
}
|
||||
|
||||
void Storage::startInjection()
|
||||
{
|
||||
// may be implemented in derived
|
||||
}
|
||||
|
||||
void Storage::finishInjection()
|
||||
{
|
||||
// may be implemented in derived
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define STORAGE_H
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "data/name/NameHierarchy.h"
|
||||
@@ -32,9 +33,13 @@ public:
|
||||
virtual void forEachCommentLocation(std::function<void(const StorageCommentLocation& /*data*/)> callback) const = 0;
|
||||
virtual void forEachError(std::function<void(const StorageError& /*data*/)> callback) const = 0;
|
||||
|
||||
void inject(Storage* injected);
|
||||
|
||||
private:
|
||||
virtual void startInjection();
|
||||
virtual void finishInjection();
|
||||
void inject(Storage* injected);
|
||||
|
||||
std::mutex m_dataMutex;
|
||||
};
|
||||
|
||||
#endif // STORAGE_H
|
||||
|
||||
@@ -12,33 +12,25 @@ TaskCleanStorage::TaskCleanStorage(
|
||||
{
|
||||
}
|
||||
|
||||
void TaskCleanStorage::enter()
|
||||
void TaskCleanStorage::doEnter()
|
||||
{
|
||||
m_dialogView->showProgressDialog("Clearing Files", std::to_string(m_filePaths.size()) + " Files");
|
||||
}
|
||||
|
||||
Task::TaskState TaskCleanStorage::update()
|
||||
Task::TaskState TaskCleanStorage::doUpdate()
|
||||
{
|
||||
m_storage->clearFileElements(m_filePaths);
|
||||
|
||||
m_filePaths.clear();
|
||||
|
||||
return Task::STATE_FINISHED;
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
void TaskCleanStorage::exit()
|
||||
void TaskCleanStorage::doExit()
|
||||
{
|
||||
m_dialogView->hideProgressDialog();
|
||||
}
|
||||
|
||||
void TaskCleanStorage::interrupt()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskCleanStorage::revert()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskCleanStorage::abort()
|
||||
void TaskCleanStorage::doReset()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -19,18 +19,15 @@ public:
|
||||
DialogView* dialogView
|
||||
);
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
PersistentStorage* m_storage;
|
||||
std::vector<FilePath> m_filePaths;
|
||||
DialogView* m_dialogView;
|
||||
};
|
||||
|
||||
#endif // TASK_PARSE_CXX_H
|
||||
#endif // TASK_CLEAN_STORAGE_H
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "data/TaskInjectStorage.h"
|
||||
|
||||
#include "data/Storage.h"
|
||||
|
||||
TaskInjectStorage::TaskInjectStorage(
|
||||
std::shared_ptr<Storage> source,
|
||||
std::shared_ptr<Storage> target
|
||||
)
|
||||
: m_source(source)
|
||||
, m_target(target)
|
||||
{
|
||||
}
|
||||
|
||||
void TaskInjectStorage::doEnter()
|
||||
{
|
||||
}
|
||||
|
||||
Task::TaskState TaskInjectStorage::doUpdate()
|
||||
{
|
||||
m_target->inject(m_source.get());
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
void TaskInjectStorage::doExit()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskInjectStorage::doReset()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef TASK_INJECT_STORAGE_H
|
||||
#define TASK_INJECT_STORAGE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "utility/scheduling/Task.h"
|
||||
|
||||
class Storage;
|
||||
|
||||
class TaskInjectStorage
|
||||
: public Task
|
||||
{
|
||||
public:
|
||||
TaskInjectStorage(
|
||||
std::shared_ptr<Storage> source,
|
||||
std::shared_ptr<Storage> target
|
||||
);
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
std::shared_ptr<Storage> m_source;
|
||||
std::shared_ptr<Storage> m_target;
|
||||
};
|
||||
|
||||
#endif // TASK_INJECT_STORAGE_H
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "data/TaskRepeatWhileUnparsedSourceFilesAvailable.h"
|
||||
|
||||
#include "utility/file/FileRegister.h"
|
||||
|
||||
TaskRepeatWhileUnparsedSourceFilesAvailable::TaskRepeatWhileUnparsedSourceFilesAvailable(
|
||||
std::shared_ptr<FileRegister> fileRegister
|
||||
)
|
||||
: m_fileRegister(fileRegister)
|
||||
{
|
||||
}
|
||||
|
||||
void TaskRepeatWhileUnparsedSourceFilesAvailable::setTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
if (task)
|
||||
{
|
||||
m_taskRunner = std::make_shared<TaskRunner>(task);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskRepeatWhileUnparsedSourceFilesAvailable::doEnter()
|
||||
{
|
||||
}
|
||||
|
||||
Task::TaskState TaskRepeatWhileUnparsedSourceFilesAvailable::doUpdate()
|
||||
{
|
||||
TaskState state = m_taskRunner->update();
|
||||
|
||||
if (state == Task::STATE_SUCCESS)
|
||||
{
|
||||
if(m_fileRegister->getUnparsedSourceFilePaths().size() != 0)
|
||||
{
|
||||
state = Task::STATE_RUNNING;
|
||||
m_taskRunner->reset();
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void TaskRepeatWhileUnparsedSourceFilesAvailable::doExit()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskRepeatWhileUnparsedSourceFilesAvailable::doReset()
|
||||
{
|
||||
m_taskRunner->reset();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef TASK_REPEAT_WHILE_UNPARSED_SOURCE_FILES_AVAILABLE_H
|
||||
#define TASK_REPEAT_WHILE_UNPARSED_SOURCE_FILES_AVAILABLE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "utility/scheduling/TaskDecorator.h"
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
|
||||
class FileRegister;
|
||||
|
||||
class TaskRepeatWhileUnparsedSourceFilesAvailable
|
||||
: public TaskDecorator
|
||||
{
|
||||
public:
|
||||
TaskRepeatWhileUnparsedSourceFilesAvailable(
|
||||
std::shared_ptr<FileRegister> fileRegister
|
||||
);
|
||||
|
||||
virtual void setTask(std::shared_ptr<Task> task);
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
std::shared_ptr<FileRegister> m_fileRegister;
|
||||
std::shared_ptr<TaskRunner> m_taskRunner;
|
||||
};
|
||||
|
||||
#endif // TASK_REPEAT_WHILE_UNPARSED_SOURCE_FILES_AVAILABLE_H
|
||||
@@ -9,11 +9,13 @@
|
||||
#include "data/parser/ParserClientImpl.h"
|
||||
#include "utility/scheduling/Task.h"
|
||||
#include "utility/TimePoint.h"
|
||||
#include "utility/messaging/type/MessageInterruptTasks.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
|
||||
class CxxParser;
|
||||
class DialogView;
|
||||
class FileRegister;
|
||||
class PersistentStorage;
|
||||
class IntermediateStorage;
|
||||
|
||||
namespace clang
|
||||
{
|
||||
@@ -25,28 +27,27 @@ namespace clang
|
||||
|
||||
class TaskParseCxx
|
||||
: public Task
|
||||
, public MessageListener<MessageInterruptTasks>
|
||||
{
|
||||
public:
|
||||
static std::vector<FilePath> getSourceFilesFromCDB(const FilePath& compilationDatabasePath);
|
||||
|
||||
TaskParseCxx(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister,
|
||||
const Parser::Arguments& arguments,
|
||||
DialogView* dialogView
|
||||
);
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
|
||||
private:
|
||||
PersistentStorage* m_storage;
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
virtual void handleMessage(MessageInterruptTasks* message);
|
||||
|
||||
std::shared_ptr<IntermediateStorage> m_storage;
|
||||
std::shared_ptr<std::mutex> m_storageMutex;
|
||||
|
||||
const Parser::Arguments m_arguments;
|
||||
@@ -57,6 +58,8 @@ private:
|
||||
|
||||
bool m_isCDB;
|
||||
std::shared_ptr<clang::tooling::JSONCompilationDatabase> m_cdb;
|
||||
|
||||
bool m_interrupted;
|
||||
};
|
||||
|
||||
#endif // TASK_PARSE_CXX_H
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "data/parser/Parser.h"
|
||||
#include "data/parser/ParserClientImpl.h"
|
||||
#include "utility/scheduling/Task.h"
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
#include "utility/scheduling/TaskDecorator.h"
|
||||
#include "utility/TimePoint.h"
|
||||
|
||||
@@ -23,20 +25,20 @@ public:
|
||||
);
|
||||
virtual ~TaskParseWrapper();
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
virtual void setTask(std::shared_ptr<Task> task);
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
PersistentStorage* m_storage;
|
||||
std::shared_ptr<FileRegister> m_fileRegister;
|
||||
DialogView* m_dialogView;
|
||||
|
||||
TimePoint m_start;
|
||||
std::shared_ptr<TaskRunner> m_taskRunner;
|
||||
};
|
||||
|
||||
#endif // TASK_PARSE_WRAPPER_H
|
||||
|
||||
@@ -5,37 +5,39 @@
|
||||
|
||||
#include "data/parser/Parser.h"
|
||||
#include "utility/scheduling/Task.h"
|
||||
#include "utility/messaging/type/MessageInterruptTasks.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
|
||||
class DialogView;
|
||||
class FileRegister;
|
||||
class PersistentStorage;
|
||||
class IntermediateStorage;
|
||||
|
||||
class TaskParseJava
|
||||
: public Task
|
||||
, public MessageListener<MessageInterruptTasks>
|
||||
{
|
||||
public:
|
||||
TaskParseJava(
|
||||
PersistentStorage* storage,
|
||||
std::shared_ptr<std::mutex> storageMutex,
|
||||
std::shared_ptr<IntermediateStorage> storage,
|
||||
std::shared_ptr<FileRegister> fileRegister,
|
||||
const Parser::Arguments& arguments,
|
||||
DialogView* dialogView
|
||||
);
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
|
||||
private:
|
||||
PersistentStorage* m_storage;
|
||||
std::shared_ptr<std::mutex> m_storageMutex;
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
virtual void handleMessage(MessageInterruptTasks* message);
|
||||
|
||||
std::shared_ptr<IntermediateStorage> m_storage;
|
||||
std::shared_ptr<FileRegister> m_fileRegister;
|
||||
Parser::Arguments m_arguments;
|
||||
DialogView* m_dialogView;
|
||||
|
||||
bool m_interrupted;
|
||||
};
|
||||
|
||||
#endif // TASK_PARSE_JAVA_H
|
||||
|
||||
@@ -230,5 +230,17 @@ size_t FileRegister::getSourceFilesCount() const
|
||||
|
||||
size_t FileRegister::getParsedSourceFilesCount() const
|
||||
{
|
||||
return getSourceFilesCount() - getUnparsedSourceFilePaths().size();
|
||||
std::lock_guard<std::mutex> lock(m_sourceFileMutex);
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
for (std::pair<FilePath, ParseState>&& p : m_sourceFilePaths)
|
||||
{
|
||||
if (p.second == STATE_PARSED)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -260,24 +260,26 @@ void MessageQueue::sendMessageAsTask(std::shared_ptr<MessageBase> message, bool
|
||||
{
|
||||
std::shared_ptr<TaskGroupSequential> taskGroup = std::make_shared<TaskGroupSequential>();
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||||
for (size_t i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
MessageListenerBase* listener = m_listeners[i];
|
||||
|
||||
if (listener->getType() == message->getType())
|
||||
std::lock_guard<std::mutex> lock(m_listenersMutex);
|
||||
for (size_t i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
uint listenerId = listener->getId();
|
||||
taskGroup->addTask(std::make_shared<TaskLambda>(
|
||||
[listenerId, message]()
|
||||
{
|
||||
MessageListenerBase* listener = MessageQueue::getInstance()->getListenerById(listenerId);
|
||||
if (listener)
|
||||
MessageListenerBase* listener = m_listeners[i];
|
||||
|
||||
if (listener->getType() == message->getType())
|
||||
{
|
||||
uint listenerId = listener->getId();
|
||||
taskGroup->addTask(std::make_shared<TaskLambda>(
|
||||
[listenerId, message]()
|
||||
{
|
||||
listener->handleMessageBase(message.get());
|
||||
MessageListenerBase* listener = MessageQueue::getInstance()->getListenerById(listenerId);
|
||||
if (listener)
|
||||
{
|
||||
listener->handleMessageBase(message.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ void Task::dispatchNext(std::shared_ptr<Task> task)
|
||||
}
|
||||
|
||||
Task::Task()
|
||||
: m_state(STATE_NEW)
|
||||
: m_enterCalled(false)
|
||||
, m_exitCalled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -22,74 +23,28 @@ Task::~Task()
|
||||
{
|
||||
}
|
||||
|
||||
Task::TaskState Task::getState() const
|
||||
Task::TaskState Task::update()
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
Task::TaskState Task::processTask()
|
||||
{
|
||||
switch (m_state)
|
||||
if (!m_enterCalled)
|
||||
{
|
||||
case STATE_NEW:
|
||||
case STATE_CANCELED:
|
||||
enter();
|
||||
case STATE_RUNNING:
|
||||
{
|
||||
TaskState newState = update();
|
||||
if (newState == STATE_NEW || newState == STATE_CANCELED)
|
||||
{
|
||||
LOG_ERROR("Task can't change to state NEW or CANCELLED");
|
||||
return m_state;
|
||||
}
|
||||
|
||||
setState(newState);
|
||||
if (m_state == STATE_FINISHED)
|
||||
{
|
||||
exit();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_FINISHED:
|
||||
break;
|
||||
doEnter();
|
||||
m_enterCalled = true;
|
||||
}
|
||||
|
||||
return m_state;
|
||||
}
|
||||
TaskState state = doUpdate();
|
||||
|
||||
Task::TaskState Task::interruptTask()
|
||||
{
|
||||
switch (m_state)
|
||||
if (state != STATE_RUNNING && !m_exitCalled)
|
||||
{
|
||||
case STATE_NEW:
|
||||
abort();
|
||||
break;
|
||||
case STATE_CANCELED:
|
||||
break;
|
||||
case STATE_RUNNING:
|
||||
interrupt();
|
||||
exit();
|
||||
break;
|
||||
case STATE_FINISHED:
|
||||
revert();
|
||||
break;
|
||||
doExit();
|
||||
m_exitCalled = true;
|
||||
}
|
||||
|
||||
setState(STATE_CANCELED);
|
||||
return m_state;
|
||||
return state;
|
||||
}
|
||||
|
||||
void Task::executeTask()
|
||||
void Task::reset()
|
||||
{
|
||||
TaskState state;
|
||||
do
|
||||
{
|
||||
state = processTask();
|
||||
}
|
||||
while (state != STATE_FINISHED);
|
||||
}
|
||||
|
||||
void Task::setState(TaskState state)
|
||||
{
|
||||
m_state = state;
|
||||
doReset();
|
||||
m_enterCalled = false;
|
||||
m_exitCalled = false;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,9 @@ class Task
|
||||
public:
|
||||
enum TaskState
|
||||
{
|
||||
STATE_NEW,
|
||||
STATE_RUNNING,
|
||||
STATE_FINISHED,
|
||||
STATE_CANCELED
|
||||
STATE_SUCCESS,
|
||||
STATE_FAILURE
|
||||
};
|
||||
|
||||
static void dispatch(std::shared_ptr<Task> task);
|
||||
@@ -20,26 +19,19 @@ public:
|
||||
Task();
|
||||
virtual ~Task();
|
||||
|
||||
TaskState getState() const;
|
||||
// virtual TaskState getState() const = 0;
|
||||
|
||||
TaskState processTask();
|
||||
TaskState interruptTask();
|
||||
|
||||
void executeTask();
|
||||
|
||||
virtual void enter() = 0;
|
||||
virtual TaskState update() = 0;
|
||||
virtual void exit() = 0;
|
||||
|
||||
virtual void interrupt() = 0;
|
||||
virtual void revert() = 0;
|
||||
virtual void abort() = 0;
|
||||
|
||||
protected:
|
||||
void setState(TaskState state);
|
||||
TaskState update();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
TaskState m_state;
|
||||
virtual void doEnter() = 0;
|
||||
virtual Task::TaskState doUpdate() = 0;
|
||||
virtual void doExit() = 0;
|
||||
virtual void doReset() = 0;
|
||||
|
||||
bool m_enterCalled;
|
||||
bool m_exitCalled;
|
||||
};
|
||||
|
||||
#endif // TASK_H
|
||||
|
||||
@@ -7,8 +7,3 @@ TaskDecorator::TaskDecorator()
|
||||
TaskDecorator::~TaskDecorator()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskDecorator::setTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
m_task = task;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,7 @@ public:
|
||||
TaskDecorator();
|
||||
virtual ~TaskDecorator();
|
||||
|
||||
void setTask(std::shared_ptr<Task> task);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Task> m_task;
|
||||
virtual void setTask(std::shared_ptr<Task> task) = 0;
|
||||
};
|
||||
|
||||
#endif // TASK_DECORATOR_H
|
||||
|
||||
@@ -7,8 +7,3 @@ TaskGroup::TaskGroup()
|
||||
TaskGroup::~TaskGroup()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskGroup::addTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
m_tasks.push_back(task);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@ public:
|
||||
TaskGroup();
|
||||
virtual ~TaskGroup();
|
||||
|
||||
void addTask(std::shared_ptr<Task> task);
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<Task>> m_tasks;
|
||||
virtual void addTask(std::shared_ptr<Task> task) = 0;
|
||||
};
|
||||
|
||||
#endif // TASK_GROUP_H
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "utility/scheduling/TaskGroupParallel.h"
|
||||
|
||||
#include "utility/ScopedFunctor.h"
|
||||
|
||||
TaskGroupParallel::TaskGroupParallel()
|
||||
: m_needsToStartThreads(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,83 +11,88 @@ TaskGroupParallel::~TaskGroupParallel()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskGroupParallel::enter()
|
||||
void TaskGroupParallel::addTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
m_interrupt = false;
|
||||
m_running = false;
|
||||
m_activeTaskCount = 0;
|
||||
m_tasks.push_back(std::make_shared<TaskInfo>(std::make_shared<TaskRunner>(task)));
|
||||
}
|
||||
|
||||
Task::TaskState TaskGroupParallel::update()
|
||||
void TaskGroupParallel::doEnter()
|
||||
{
|
||||
if (!m_running)
|
||||
m_taskFailed = false;
|
||||
|
||||
if (m_needsToStartThreads)
|
||||
{
|
||||
m_needsToStartThreads = false;
|
||||
m_activeTaskCount = 0;
|
||||
for (size_t i = 0; i < m_tasks.size(); i++)
|
||||
{
|
||||
m_threads.push_back(std::thread(&TaskGroupParallel::processTaskThreaded, this, m_tasks[i]));
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_activeTaskCountMutex);
|
||||
m_tasks[i]->thread = std::make_shared<std::thread>(&TaskGroupParallel::processTaskThreaded, this, m_tasks[i]);
|
||||
m_tasks[i]->active = true;
|
||||
m_activeTaskCount++;
|
||||
}
|
||||
m_running = true;
|
||||
}
|
||||
}
|
||||
|
||||
Task::TaskState TaskGroupParallel::doUpdate()
|
||||
{
|
||||
if (m_tasks.size() != 0 && getActveTaskCount() > 0)
|
||||
{
|
||||
return STATE_RUNNING;
|
||||
}
|
||||
|
||||
int activeTaskCount = 0;
|
||||
return (m_taskFailed ? STATE_FAILURE : STATE_SUCCESS);
|
||||
}
|
||||
|
||||
void TaskGroupParallel::doExit()
|
||||
{
|
||||
for (size_t i = 0; i < m_tasks.size(); i++)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_activeTaskCountMutex);
|
||||
activeTaskCount = m_activeTaskCount;
|
||||
m_tasks[i]->thread->join();
|
||||
m_tasks[i]->thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (activeTaskCount == 0)
|
||||
void TaskGroupParallel::doReset()
|
||||
{
|
||||
for (size_t i = 0; i < m_tasks.size(); i++)
|
||||
{
|
||||
return (m_interrupt ? STATE_CANCELED : STATE_FINISHED);
|
||||
}
|
||||
|
||||
return Task::STATE_RUNNING;
|
||||
}
|
||||
|
||||
void TaskGroupParallel::exit()
|
||||
{
|
||||
for (size_t i = 0; i < m_threads.size(); i++)
|
||||
{
|
||||
m_threads[i].join();
|
||||
}
|
||||
m_threads.clear();
|
||||
}
|
||||
|
||||
void TaskGroupParallel::interrupt()
|
||||
{
|
||||
m_interrupt = true;
|
||||
}
|
||||
|
||||
void TaskGroupParallel::revert()
|
||||
{
|
||||
m_interrupt = true;
|
||||
}
|
||||
|
||||
void TaskGroupParallel::abort()
|
||||
{
|
||||
m_interrupt = true;
|
||||
}
|
||||
|
||||
|
||||
void TaskGroupParallel::processTaskThreaded(std::shared_ptr<Task> task)
|
||||
{
|
||||
Task::TaskState state = Task::STATE_NEW;
|
||||
while (state != Task::STATE_FINISHED && state != Task::STATE_CANCELED)
|
||||
{
|
||||
if (m_interrupt)
|
||||
m_tasks[i]->taskRunner->reset();
|
||||
if (!m_tasks[i]->active)
|
||||
{
|
||||
state = task->interruptTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = task->processTask();
|
||||
m_tasks[i]->thread->join();
|
||||
m_tasks[i]->thread = std::make_shared<std::thread>(&TaskGroupParallel::processTaskThreaded, this, m_tasks[i]);
|
||||
m_tasks[i]->active = true;
|
||||
m_activeTaskCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
void TaskGroupParallel::processTaskThreaded(std::shared_ptr<TaskInfo> taskInfo)
|
||||
{
|
||||
ScopedFunctor functor([&](){
|
||||
std::lock_guard<std::mutex> lock(m_activeTaskCountMutex);
|
||||
m_activeTaskCount--; // not safe! if exception hits this thread before this point the count is not decremented.
|
||||
m_activeTaskCount--;
|
||||
});
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
TaskState state = taskInfo->taskRunner->update();
|
||||
|
||||
if (state != STATE_RUNNING)
|
||||
{
|
||||
if (state == STATE_FAILURE)
|
||||
{
|
||||
m_taskFailed = true;
|
||||
}
|
||||
taskInfo->active = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TaskGroupParallel::getActveTaskCount() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_activeTaskCountMutex);
|
||||
return m_activeTaskCount;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef TASK_GROUP_PARALLEL_H
|
||||
#define TASK_GROUP_PARALLEL_H
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "utility/scheduling/TaskGroup.h"
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
|
||||
class TaskGroupParallel
|
||||
: public TaskGroup
|
||||
@@ -13,24 +15,34 @@ public:
|
||||
TaskGroupParallel();
|
||||
virtual ~TaskGroupParallel();
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
virtual void addTask(std::shared_ptr<Task> task);
|
||||
|
||||
private:
|
||||
void processTaskThreaded(std::shared_ptr<Task> task);
|
||||
struct TaskInfo
|
||||
{
|
||||
TaskInfo(std::shared_ptr<TaskRunner> taskRunner)
|
||||
: taskRunner(taskRunner)
|
||||
, active(false)
|
||||
{}
|
||||
std::shared_ptr<TaskRunner> taskRunner;
|
||||
std::shared_ptr<std::thread> thread;
|
||||
volatile bool active;
|
||||
};
|
||||
|
||||
volatile bool m_interrupt;
|
||||
bool m_running;
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
std::vector<std::thread> m_threads;
|
||||
void processTaskThreaded(std::shared_ptr<TaskInfo> taskInfo);
|
||||
int getActveTaskCount() const;
|
||||
|
||||
std::vector<std::shared_ptr<TaskInfo>> m_tasks;
|
||||
bool m_needsToStartThreads;
|
||||
|
||||
volatile bool m_taskFailed;
|
||||
volatile int m_activeTaskCount;
|
||||
std::mutex m_activeTaskCountMutex;
|
||||
mutable std::mutex m_activeTaskCountMutex;
|
||||
};
|
||||
|
||||
#endif // TASK_GROUP_PARALLEL_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "utility/scheduling/TaskGroupSequential.h"
|
||||
#include <iostream>
|
||||
|
||||
TaskGroupSequential::TaskGroupSequential()
|
||||
: m_taskIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9,55 +9,49 @@ TaskGroupSequential::~TaskGroupSequential()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskGroupSequential::enter()
|
||||
void TaskGroupSequential::addTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
m_taskRunners.push_back(std::make_shared<TaskRunner>(task));
|
||||
}
|
||||
|
||||
Task::TaskState TaskGroupSequential::update()
|
||||
void TaskGroupSequential::doEnter()
|
||||
{
|
||||
if (!m_tasks.size())
|
||||
m_taskIndex = 0;
|
||||
}
|
||||
|
||||
Task::TaskState TaskGroupSequential::doUpdate()
|
||||
{
|
||||
if (m_taskIndex >= int(m_taskRunners.size()))
|
||||
{
|
||||
return Task::STATE_FINISHED;
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
else if (m_taskIndex < 0)
|
||||
{
|
||||
return STATE_FAILURE;
|
||||
}
|
||||
|
||||
if (m_taskIndex < 0 || m_tasks[m_taskIndex]->getState() != Task::STATE_RUNNING)
|
||||
TaskState state = m_taskRunners[m_taskIndex]->update();
|
||||
|
||||
if (state == STATE_SUCCESS)
|
||||
{
|
||||
m_taskIndex++;
|
||||
}
|
||||
|
||||
std::shared_ptr<Task> task = m_tasks[m_taskIndex];
|
||||
|
||||
TaskState state = task->processTask();
|
||||
|
||||
if (state == Task::STATE_FINISHED && size_t(m_taskIndex + 1) == m_tasks.size())
|
||||
else if (state == STATE_FAILURE)
|
||||
{
|
||||
return Task::STATE_FINISHED;
|
||||
m_taskIndex = -1;
|
||||
}
|
||||
|
||||
return Task::STATE_RUNNING;
|
||||
return STATE_RUNNING;
|
||||
}
|
||||
|
||||
void TaskGroupSequential::exit()
|
||||
void TaskGroupSequential::doExit()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskGroupSequential::interrupt()
|
||||
void TaskGroupSequential::doReset()
|
||||
{
|
||||
for (size_t i = 0; i < m_tasks.size(); i++)
|
||||
for (size_t i = 0; i < m_taskRunners.size(); i++)
|
||||
{
|
||||
m_tasks[i]->interruptTask();
|
||||
m_taskRunners[i]->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskGroupSequential::revert()
|
||||
{
|
||||
for (int i = m_tasks.size() - 1; i >= 0; i--)
|
||||
{
|
||||
m_tasks[i]->interruptTask();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskGroupSequential::abort()
|
||||
{
|
||||
interrupt();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define TASK_GROUP_SEQUENTIAL_H
|
||||
|
||||
#include "utility/scheduling/TaskGroup.h"
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
|
||||
class TaskGroupSequential
|
||||
: public TaskGroup
|
||||
@@ -10,15 +11,15 @@ public:
|
||||
TaskGroupSequential();
|
||||
virtual ~TaskGroupSequential();
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
virtual void addTask(std::shared_ptr<Task> task);
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
std::vector<std::shared_ptr<TaskRunner>> m_taskRunners;
|
||||
int m_taskIndex;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,28 +9,20 @@ TaskLambda::~TaskLambda()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskLambda::enter()
|
||||
void TaskLambda::doEnter()
|
||||
{
|
||||
}
|
||||
|
||||
Task::TaskState TaskLambda::update()
|
||||
Task::TaskState TaskLambda::doUpdate()
|
||||
{
|
||||
m_func();
|
||||
return Task::STATE_FINISHED;
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
void TaskLambda::exit()
|
||||
void TaskLambda::doExit()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskLambda::interrupt()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskLambda::revert()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskLambda::abort()
|
||||
void TaskLambda::doReset()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -12,15 +12,12 @@ public:
|
||||
TaskLambda(std::function<void()> func);
|
||||
virtual ~TaskLambda();
|
||||
|
||||
virtual void enter();
|
||||
virtual TaskState update();
|
||||
virtual void exit();
|
||||
|
||||
virtual void interrupt();
|
||||
virtual void revert();
|
||||
virtual void abort();
|
||||
|
||||
private:
|
||||
virtual void doEnter();
|
||||
virtual TaskState doUpdate();
|
||||
virtual void doExit();
|
||||
virtual void doReset();
|
||||
|
||||
std::function<void()> m_func;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
|
||||
TaskRunner::TaskRunner(std::shared_ptr<Task> task)
|
||||
: m_task(task)
|
||||
, m_reset(false)
|
||||
{
|
||||
}
|
||||
|
||||
TaskRunner::~TaskRunner()
|
||||
{
|
||||
}
|
||||
|
||||
//Task::TaskState TaskRunner::getState() const
|
||||
//{
|
||||
// return m_task->getState();
|
||||
//}
|
||||
|
||||
Task::TaskState TaskRunner::update()
|
||||
{
|
||||
if (m_reset)
|
||||
{
|
||||
m_task->reset();
|
||||
m_reset = false;
|
||||
}
|
||||
|
||||
return m_task->update();
|
||||
}
|
||||
|
||||
void TaskRunner::reset()
|
||||
{
|
||||
m_reset = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef TASK_RUNNER_H
|
||||
#define TASK_RUNNER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "utility/scheduling/Task.h"
|
||||
|
||||
class TaskRunner
|
||||
{
|
||||
public:
|
||||
TaskRunner(std::shared_ptr<Task> task);
|
||||
~TaskRunner();
|
||||
|
||||
//Task::TaskState getState() const;
|
||||
|
||||
Task::TaskState update();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Task> m_task;
|
||||
bool m_reset;
|
||||
};
|
||||
|
||||
#endif // TASK_H
|
||||
@@ -19,29 +19,23 @@ std::shared_ptr<TaskScheduler> TaskScheduler::getInstance()
|
||||
void TaskScheduler::pushTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
m_tasks.push_back(task);
|
||||
m_taskRunners.push_back(std::make_shared<TaskRunner>(task));
|
||||
}
|
||||
|
||||
void TaskScheduler::pushNextTask(std::shared_ptr<Task> task)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
|
||||
if (m_tasks.size() == 0)
|
||||
if (m_taskRunners.size() == 0)
|
||||
{
|
||||
m_tasks.push_front(task);
|
||||
m_taskRunners.push_front(std::make_shared<TaskRunner>(task));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tasks.insert(m_tasks.begin() + 1, task);
|
||||
m_taskRunners.insert(m_taskRunners.begin() + 1, std::make_shared<TaskRunner>(task));
|
||||
}
|
||||
}
|
||||
|
||||
void TaskScheduler::interruptCurrentTask()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
m_interruptTask = true;
|
||||
}
|
||||
|
||||
void TaskScheduler::startSchedulerLoopThreaded()
|
||||
{
|
||||
std::thread(&TaskScheduler::startSchedulerLoop, this).detach();
|
||||
@@ -57,7 +51,7 @@ void TaskScheduler::startSchedulerLoop()
|
||||
|
||||
if (m_loopIsRunning)
|
||||
{
|
||||
LOG_ERROR("Loop is already running");
|
||||
LOG_ERROR("Unable to start task scheduler. Loop is already running.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,14 +91,12 @@ void TaskScheduler::stopSchedulerLoop()
|
||||
|
||||
if (!m_loopIsRunning)
|
||||
{
|
||||
LOG_WARNING("Loop is not running");
|
||||
LOG_WARNING("Unable to stop task scheduler. Loop is not running.");
|
||||
}
|
||||
|
||||
m_loopIsRunning = false;
|
||||
}
|
||||
|
||||
interruptCurrentTask();
|
||||
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
@@ -129,7 +121,7 @@ bool TaskScheduler::loopIsRunning() const
|
||||
bool TaskScheduler::hasTasksQueued() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
return m_tasks.size();
|
||||
return m_taskRunners.size();
|
||||
}
|
||||
|
||||
std::shared_ptr<TaskScheduler> TaskScheduler::s_instance;
|
||||
@@ -137,7 +129,6 @@ std::shared_ptr<TaskScheduler> TaskScheduler::s_instance;
|
||||
TaskScheduler::TaskScheduler()
|
||||
: m_loopIsRunning(false)
|
||||
, m_threadIsRunning(false)
|
||||
, m_interruptTask(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -145,41 +136,19 @@ void TaskScheduler::processTasks()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
|
||||
while (m_tasks.size())
|
||||
while (m_taskRunners.size())
|
||||
{
|
||||
bool interrupt = m_interruptTask;
|
||||
m_interruptTask = false;
|
||||
|
||||
std::shared_ptr<Task> task = m_tasks.front();
|
||||
Task::TaskState state;
|
||||
std::shared_ptr<TaskRunner> runner = m_taskRunners.front();
|
||||
|
||||
m_tasksMutex.unlock();
|
||||
if (interrupt)
|
||||
{
|
||||
state = task->interruptTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = task->processTask();
|
||||
}
|
||||
|
||||
Task::TaskState state = runner->update();
|
||||
|
||||
m_tasksMutex.lock();
|
||||
|
||||
if (state == Task::STATE_FINISHED || state == Task::STATE_CANCELED)
|
||||
if (state != Task::STATE_RUNNING)
|
||||
{
|
||||
m_tasks.pop_front();
|
||||
m_taskRunners.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
m_interruptTask = false;
|
||||
}
|
||||
|
||||
void TaskScheduler::handleMessage(MessageInterruptTasks* message)
|
||||
{
|
||||
interruptCurrentTask();
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_tasksMutex);
|
||||
if (m_tasks.size())
|
||||
{
|
||||
MessageStatus("Stop running tasks...", false, true).dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageInterruptTasks.h"
|
||||
#include "utility/scheduling/Task.h"
|
||||
#include "utility/scheduling/TaskRunner.h"
|
||||
|
||||
class TaskScheduler
|
||||
: public MessageListener<MessageInterruptTasks>
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<TaskScheduler> getInstance();
|
||||
|
||||
void pushTask(std::shared_ptr<Task> task);
|
||||
void pushNextTask(std::shared_ptr<Task> task);
|
||||
void interruptCurrentTask();
|
||||
|
||||
void startSchedulerLoopThreaded();
|
||||
void startSchedulerLoop();
|
||||
@@ -35,13 +34,11 @@ private:
|
||||
|
||||
void processTasks();
|
||||
|
||||
virtual void handleMessage(MessageInterruptTasks* message);
|
||||
|
||||
bool m_loopIsRunning;
|
||||
bool m_threadIsRunning;
|
||||
|
||||
std::deque<std::shared_ptr<Task>> m_tasks;
|
||||
bool m_interruptTask;
|
||||
std::deque<std::shared_ptr<TaskRunner>> m_taskRunners;
|
||||
|
||||
mutable std::mutex m_tasksMutex;
|
||||
mutable std::mutex m_loopMutex;
|
||||
|
||||
Reference in New Issue
Block a user