// Copyright (C) 2025 Jarek Kobus // Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only // Qt-Security score:significant reason:default #ifndef QTASKTREE_QBARRIERTASK_H #define QTASKTREE_QBARRIERTASK_H #include #include #include QT_BEGIN_NAMESPACE namespace QtTaskTree { class WhenPrivate; } QT_DECLARE_QESDP_SPECIALIZATION_DTOR(QtTaskTree::WhenPrivate) namespace QtTaskTree { class QBarrierPrivate; class Q_TASKTREE_EXPORT QBarrier : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QBarrier) public: QBarrier() : QBarrier(nullptr) {} explicit QBarrier(QObject *parent); ~QBarrier() override; void setLimit(qsizetype value); qsizetype limit() const; void start(); void advance(); void stopWithResult(DoneResult result); bool isRunning() const; qsizetype current() const; std::optional result() const; Q_SIGNALS: void done(QtTaskTree::DoneResult success, QPrivateSignal); protected: bool event(QEvent *event) override; }; using QBarrierTask = QCustomTask; class Q_TASKTREE_EXPORT QStartedBarrier : public QBarrier { Q_OBJECT public: QStartedBarrier() : QStartedBarrier(nullptr) {} explicit QStartedBarrier(QObject *parent); explicit QStartedBarrier(qsizetype limit, QObject *parent = nullptr); ~QStartedBarrier() override; protected: bool event(QEvent *event) override; }; using QStoredBarrier = Storage; Q_TASKTREE_EXPORT ExecutableItem barrierAwaiterTask(const QStoredBarrier &storedBarrier); template ExecutableItem signalAwaiterTask(const typename QtPrivate::FunctionPointer::Object *sender, Signal signal) { return QBarrierTask([sender, signal](QBarrier &barrier) { QObject::connect(sender, signal, &barrier, &QBarrier::advance, Qt::SingleShotConnection); }); } using BarrierKickerGetter = std::function; class When final { public: Q_TASKTREE_EXPORT explicit When(const BarrierKickerGetter &kicker, WorkflowPolicy policy = WorkflowPolicy::StopOnError); template explicit When(const QCustomTask &customTask, Signal signal, WorkflowPolicy policy = WorkflowPolicy::StopOnError) : When(kickerForSignal(customTask, signal), policy) {} QT_TASKTREE_DECLARE_SMFS(When, Q_TASKTREE_EXPORT) private: Q_TASKTREE_EXPORT friend Group operator>>(const When &whenItem, const Do &doItem); template static BarrierKickerGetter kickerForSignal(const QCustomTask &task, Signal signal) { return [taskHandler = task.taskHandler(), signal](const QStoredBarrier &barrier) { auto handler = std::move(taskHandler); const auto wrappedSetupHandler = [originalSetupHandler = std::move(handler.m_taskAdapterSetupHandler), barrier, signal](void *taskAdapter) { const SetupResult setupResult = std::invoke(originalSetupHandler, taskAdapter); using TaskAdapter = typename QCustomTask::TaskAdapter; TaskAdapter *adapter = static_cast(taskAdapter); QObject::connect(adapter->task.get(), signal, barrier.activeStorage(), &QBarrier::advance); return setupResult; }; handler.m_taskAdapterSetupHandler = std::move(wrappedSetupHandler); return ExecutableItem(std::move(handler)); }; } QExplicitlySharedDataPointer d; }; } // namespace QtTaskTree QT_END_NAMESPACE #endif // QTASKTREE_QBARRIERTASK_H