36 #include <QMutexLocker>
37 #include <QFutureInterface>
51 std::atomic_bool IsPaused_ {
false };
53 QMutex FunctionsMutex_;
54 QList<std::function<void ()>> Functions_;
56 using QThread::QThread;
58 void SetPaused (
bool);
61 QFuture<std::result_of_t<F ()>> ScheduleImpl (F func)
64 iface.reportStarted ();
66 auto reporting = [func, iface] ()
mutable
68 ReportFutureResult (iface, func);
72 QMutexLocker locker { &FunctionsMutex_ };
73 Functions_ << reporting;
78 return iface.future ();
81 template<
typename F,
typename... Args>
82 QFuture<std::result_of_t<F (Args...)>> ScheduleImpl (F
f, Args&&... args)
84 return ScheduleImpl ([
f, args...] ()
mutable { return std::invoke (f, args...); });
87 virtual size_t GetQueueSize ();
91 virtual
void Initialize () = 0;
92 virtual
void Cleanup () = 0;
101 template<
typename WorkerType>
102 struct InitializerBase
104 virtual std::unique_ptr<WorkerType> Initialize () = 0;
106 virtual ~InitializerBase () =
default;
109 template<
typename WorkerType,
typename... Args>
110 struct Initializer final : InitializerBase<WorkerType>
112 std::tuple<Args...> Args_;
114 Initializer (std::tuple<Args...>&& tuple)
115 : Args_ { std::move (tuple) }
119 std::unique_ptr<WorkerType> Initialize ()
override
121 return std::apply ([] (
auto&&... args) {
return std::make_unique<WorkerType> (std::forward<Args> (args)...); }, Args_);
125 template<
typename WorkerType>
126 struct Initializer<WorkerType> final : InitializerBase<WorkerType>
128 std::unique_ptr<WorkerType> Initialize ()
override
130 return std::make_unique<WorkerType> ();
135 template<
typename WorkerType>
138 std::atomic_bool IsAutoQuit_ {
false };
139 unsigned long QuitWait_ = 2000;
141 using W = WorkerType;
143 std::unique_ptr<WorkerType> Worker_;
145 std::unique_ptr<detail::InitializerBase<WorkerType>> Initializer_;
149 , Initializer_ { std::make_unique<detail::Initializer<WorkerType>> () }
153 template<
typename... Args>
156 , Initializer_ { std::make_unique<detail::Initializer<WorkerType, std::decay_t<Args>...>> (std::tuple<std::decay_t<Args>...> { args... }) }
163 typename = std::enable_if_t<
164 !std::is_base_of<QObject, std::remove_pointer_t<std::decay_t<Head>>>::value
168 :
WorkerThread { static_cast<QObject*> (
nullptr), head, rest... }
181 qWarning () << Q_FUNC_INFO
182 <<
"thread is still running";
185 void SetAutoQuit (
bool autoQuit)
187 IsAutoQuit_ = autoQuit;
190 void SetQuitWait (
unsigned long wait)
197 template<
typename F,
typename... Args>
198 QFuture<std::result_of_t<F (WorkerType*, Args...)>> ScheduleImpl (F
f, Args&&... args)
200 const auto fWrapped = [
f,
this] (
auto... args)
mutable {
return std::invoke (
f, Worker_.get (), args...); };
204 void Initialize ()
override
206 Worker_ = Initializer_->Initialize ();
208 Initializer_.reset ();
211 void Cleanup ()
override