LeechCraft 0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
workerthreadbase.h
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#pragma once
10
11#include <functional>
12#include <atomic>
13#include <QThread>
14#include <QMutex>
15#include <QMutexLocker>
16#include <QFutureInterface>
17#include <QFuture>
18#include <QList>
19#include "futures.h"
20#include "threadsconfig.h"
21
22namespace LC::Util
23{
24 class UTIL_THREADS_API WorkerThreadBase : public QThread
25 {
26 Q_OBJECT
27
28 std::atomic_bool IsPaused_ { false };
29
30 QMutex FunctionsMutex_;
31 QList<std::function<void ()>> Functions_;
32 public:
33 using QThread::QThread;
34
35 void SetPaused (bool);
36
37 template<typename F>
38 QFuture<std::result_of_t<F ()>> ScheduleImpl (F func)
39 {
40 QFutureInterface<std::result_of_t<F ()>> iface;
41 iface.reportStarted ();
42
43 auto reporting = [func, iface] () mutable
44 {
45 ReportFutureResult (iface, func);
46 };
47
48 {
49 QMutexLocker locker { &FunctionsMutex_ };
50 Functions_ << reporting;
51 }
52
53 emit rotateFuncs ();
54
55 return iface.future ();
56 }
57
58 template<typename F, typename... Args>
59 QFuture<std::result_of_t<F (Args...)>> ScheduleImpl (F f, Args&&... args)
60 {
61 return ScheduleImpl ([f, args...] () mutable { return std::invoke (f, args...); });
62 }
63
64 virtual size_t GetQueueSize ();
65 protected:
66 void run () final;
67
68 virtual void Initialize () = 0;
69 virtual void Cleanup () = 0;
70 private:
71 void RotateFuncs ();
72 signals:
73 void rotateFuncs ();
74 };
75
76 namespace detail
77 {
78 template<typename WorkerType>
80 {
81 virtual std::unique_ptr<WorkerType> Initialize () = 0;
82
83 virtual ~InitializerBase () = default;
84 };
85
86 template<typename WorkerType, typename... Args>
87 struct Initializer final : InitializerBase<WorkerType>
88 {
89 std::tuple<Args...> Args_;
90
91 Initializer (std::tuple<Args...>&& tuple)
92 : Args_ { std::move (tuple) }
93 {
94 }
95
96 std::unique_ptr<WorkerType> Initialize () override
97 {
98 return std::apply ([] (auto&&... args) { return std::make_unique<WorkerType> (std::forward<Args> (args)...); }, Args_);
99 }
100 };
101
102 template<typename WorkerType>
103 struct Initializer<WorkerType> final : InitializerBase<WorkerType>
104 {
105 std::unique_ptr<WorkerType> Initialize () override
106 {
107 return std::make_unique<WorkerType> ();
108 }
109 };
110 }
111
112 template<typename WorkerType>
114 {
115 std::atomic_bool IsAutoQuit_ { false };
116 unsigned long QuitWait_ = 2000;
117 protected:
118 using W = WorkerType;
119
120 std::unique_ptr<WorkerType> Worker_;
121
122 std::unique_ptr<detail::InitializerBase<WorkerType>> Initializer_;
123 public:
124 WorkerThread (QObject *parent = nullptr)
125 : WorkerThreadBase { parent }
126 , Initializer_ { std::make_unique<detail::Initializer<WorkerType>> () }
127 {
128 }
129
130 template<typename... Args>
131 WorkerThread (QObject *parent, const Args&... args)
132 : WorkerThreadBase { parent }
133 , Initializer_ { std::make_unique<detail::Initializer<WorkerType, std::decay_t<Args>...>> (std::tuple<std::decay_t<Args>...> { args... }) }
134 {
135 }
136
137 template<
138 typename Head,
139 typename... Rest,
140 typename = std::enable_if_t<
141 !std::is_base_of<QObject, std::remove_pointer_t<std::decay_t<Head>>>::value
142 >
143 >
144 WorkerThread (const Head& head, const Rest&... rest)
145 : WorkerThread { static_cast<QObject*> (nullptr), head, rest... }
146 {
147 }
148
150 {
151 if (!IsAutoQuit_)
152 return;
153
154 quit ();
155 wait (QuitWait_);
156
157 if (isRunning ())
158 qWarning () << Q_FUNC_INFO
159 << "thread is still running";
160 }
161
162 void SetAutoQuit (bool autoQuit)
163 {
164 IsAutoQuit_ = autoQuit;
165 }
166
167 void SetQuitWait (unsigned long wait)
168 {
169 QuitWait_ = wait;
170 }
171
173
174 template<typename F, typename... Args>
175 QFuture<std::result_of_t<F (WorkerType*, Args...)>> ScheduleImpl (F f, Args&&... args)
176 {
177 const auto fWrapped = [f, this] (auto... args) mutable { return std::invoke (f, Worker_.get (), args...); };
178 return WorkerThreadBase::ScheduleImpl (fWrapped, std::forward<Args> (args)...);
179 }
180 protected:
181 void Initialize () override
182 {
183 Worker_ = Initializer_->Initialize ();
184
185 Initializer_.reset ();
186 }
187
188 void Cleanup () override
189 {
190 Worker_.reset ();
191 }
192 };
193}
virtual void Initialize()=0
QFuture< std::result_of_t< F(Args...)> > ScheduleImpl(F f, Args &&... args)
virtual void Cleanup()=0
QFuture< std::result_of_t< F()> > ScheduleImpl(F func)
WorkerThread(QObject *parent=nullptr)
WorkerThread(const Head &head, const Rest &... rest)
void SetQuitWait(unsigned long wait)
WorkerThread(QObject *parent, const Args &... args)
std::unique_ptr< detail::InitializerBase< WorkerType > > Initializer_
void SetAutoQuit(bool autoQuit)
std::unique_ptr< WorkerType > Worker_
QFuture< std::result_of_t< F(WorkerType *, Args...)> > ScheduleImpl(F f, Args &&... args)
STL namespace.
std::unique_ptr< WorkerType > Initialize() override
virtual std::unique_ptr< WorkerType > Initialize()=0
virtual ~InitializerBase()=default
Initializer(std::tuple< Args... > &&tuple)
std::tuple< Args... > Args_
std::unique_ptr< WorkerType > Initialize() override
#define UTIL_THREADS_API