diff --git a/src/libs/utils/tasktree.cpp b/src/libs/utils/tasktree.cpp index fcf47d50650..c99729a5d83 100644 --- a/src/libs/utils/tasktree.cpp +++ b/src/libs/utils/tasktree.cpp @@ -9,6 +9,57 @@ namespace Utils { namespace Tasking { +bool TreeStorageBase::isValid() const +{ + return m_storageData && m_storageData->m_constructor && m_storageData->m_destructor; +} + +TreeStorageBase::TreeStorageBase(StorageConstructor ctor, StorageDestructor dtor) + : m_storageData(new StorageData{ctor, dtor}) { } + +void *TreeStorageBase::activeStorageVoid() const +{ + QTC_ASSERT(m_storageData->m_activeStorage, return nullptr); + const auto it = m_storageData->m_storageHash.constFind(m_storageData->m_activeStorage); + QTC_ASSERT(it != m_storageData->m_storageHash.constEnd(), return nullptr); + return it.value(); +} + +int TreeStorageBase::createStorage() +{ + QTC_ASSERT(m_storageData->m_constructor, return 0); // TODO: add isValid()? + QTC_ASSERT(m_storageData->m_destructor, return 0); + QTC_ASSERT(m_storageData->m_activeStorage == 0, return 0); // TODO: should be allowed? + const int newId = ++m_storageData->m_storageCounter; + m_storageData->m_storageHash.insert(newId, m_storageData->m_constructor()); + return newId; +} + +void TreeStorageBase::deleteStorage(int id) +{ + QTC_ASSERT(m_storageData->m_constructor, return); // TODO: add isValid()? + QTC_ASSERT(m_storageData->m_destructor, return); + QTC_ASSERT(m_storageData->m_activeStorage == 0, return); // TODO: should be allowed? + const auto it = m_storageData->m_storageHash.find(id); + QTC_ASSERT(it != m_storageData->m_storageHash.end(), return); + m_storageData->m_destructor(it.value()); + m_storageData->m_storageHash.erase(it); +} + +// passing 0 deactivates currently active storage +void TreeStorageBase::activateStorage(int id) +{ + if (id == 0) { + QTC_ASSERT(m_storageData->m_activeStorage, return); + m_storageData->m_activeStorage = 0; + return; + } + QTC_ASSERT(m_storageData->m_activeStorage == 0, return); + const auto it = m_storageData->m_storageHash.find(id); + QTC_ASSERT(it != m_storageData->m_storageHash.end(), return); + m_storageData->m_activeStorage = id; +} + Execute sequential(ExecuteMode::Sequential); Execute parallel(ExecuteMode::Parallel); Workflow stopOnError(WorkflowPolicy::StopOnError); diff --git a/src/libs/utils/tasktree.h b/src/libs/utils/tasktree.h index 16c81766eec..9f54d6a3da6 100644 --- a/src/libs/utils/tasktree.h +++ b/src/libs/utils/tasktree.h @@ -7,8 +7,12 @@ #include #include +#include namespace Utils { + +class TaskContainer; + namespace Tasking { class QTCREATOR_UTILS_EXPORT TaskInterface : public QObject @@ -23,6 +27,51 @@ signals: void done(bool success); }; +class QTCREATOR_UTILS_EXPORT TreeStorageBase +{ +public: + bool isValid() const; + +protected: + using StorageConstructor = std::function; + using StorageDestructor = std::function; + + TreeStorageBase(StorageConstructor ctor, StorageDestructor dtor); + void *activeStorageVoid() const; + +private: + int createStorage(); + void deleteStorage(int id); + void activateStorage(int id); + + struct StorageData { + StorageConstructor m_constructor = {}; + StorageDestructor m_destructor = {}; + QHash m_storageHash = {}; + int m_activeStorage = 0; // 0 means no active storage + int m_storageCounter = 0; + }; + QSharedPointer m_storageData; + friend TaskContainer; +}; + +template +class TreeStorage : public TreeStorageBase +{ +public: + TreeStorage() : TreeStorageBase(TreeStorage::ctor(), TreeStorage::dtor()) {} + StorageStruct *operator->() const noexcept { return activeStorage(); } + +private: + StorageStruct *activeStorage() const { + return static_cast(activeStorageVoid()); + } + static StorageConstructor ctor() { return [] { return new StorageStruct; }; } + static StorageDestructor dtor() { + return [](void *storage) { delete static_cast(storage); }; + } +}; + enum class ExecuteMode { Sequential, // default Parallel