LeechCraft  0.6.70-13729-g7046a9d2a7
Modular cross-platform feature rich live environment.
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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #pragma once
31 
32 #include <functional>
33 #include <atomic>
34 #include <QThread>
35 #include <QMutex>
36 #include <QMutexLocker>
37 #include <QFutureInterface>
38 #include <QFuture>
39 #include <QList>
40 #include "futures.h"
41 #include "threadsconfig.h"
42 
43 namespace LC
44 {
45 namespace Util
46 {
47  class UTIL_THREADS_API WorkerThreadBase : public QThread
48  {
49  Q_OBJECT
50 
51  std::atomic_bool IsPaused_ { false };
52 
53  QMutex FunctionsMutex_;
54  QList<std::function<void ()>> Functions_;
55  public:
56  using QThread::QThread;
57 
58  void SetPaused (bool);
59 
60  template<typename F>
62  {
64  iface.reportStarted ();
65 
66  auto reporting = [func, iface] () mutable
67  {
68  ReportFutureResult (iface, func);
69  };
70 
71  {
72  QMutexLocker locker { &FunctionsMutex_ };
73  Functions_ << reporting;
74  }
75 
76  emit rotateFuncs ();
77 
78  return iface.future ();
79  }
80 
81  template<typename F, typename... Args>
82  QFuture<std::result_of_t<F (Args...)>> ScheduleImpl (F f, Args&&... args)
83  {
84  return ScheduleImpl ([f, args...] () mutable { return std::invoke (f, args...); });
85  }
86 
87  virtual size_t GetQueueSize ();
88  protected:
89  void run () final;
90 
91  virtual void Initialize () = 0;
92  virtual void Cleanup () = 0;
93  private:
94  void RotateFuncs ();
95  signals:
96  void rotateFuncs ();
97  };
98 
99  namespace detail
100  {
101  template<typename WorkerType>
103  {
104  virtual std::unique_ptr<WorkerType> Initialize () = 0;
105 
106  virtual ~InitializerBase () = default;
107  };
108 
109  template<typename WorkerType, typename... Args>
110  struct Initializer final : InitializerBase<WorkerType>
111  {
112  std::tuple<Args...> Args_;
113 
114  Initializer (std::tuple<Args...>&& tuple)
115  : Args_ { std::move (tuple) }
116  {
117  }
118 
119  std::unique_ptr<WorkerType> Initialize () override
120  {
121  return std::apply ([] (auto&&... args) { return std::make_unique<WorkerType> (std::forward<Args> (args)...); }, Args_);
122  }
123  };
124 
125  template<typename WorkerType>
126  struct Initializer<WorkerType> final : InitializerBase<WorkerType>
127  {
128  std::unique_ptr<WorkerType> Initialize () override
129  {
130  return std::make_unique<WorkerType> ();
131  }
132  };
133  }
134 
135  template<typename WorkerType>
137  {
138  std::atomic_bool IsAutoQuit_ { false };
139  unsigned long QuitWait_ = 2000;
140  protected:
141  using W = WorkerType;
142 
143  std::unique_ptr<WorkerType> Worker_;
144 
145  std::unique_ptr<detail::InitializerBase<WorkerType>> Initializer_;
146  public:
147  WorkerThread (QObject *parent = nullptr)
148  : WorkerThreadBase { parent }
149  , Initializer_ { std::make_unique<detail::Initializer<WorkerType>> () }
150  {
151  }
152 
153  template<typename... Args>
154  WorkerThread (QObject *parent, const Args&... args)
155  : WorkerThreadBase { parent }
156  , Initializer_ { std::make_unique<detail::Initializer<WorkerType, std::decay_t<Args>...>> (std::tuple<std::decay_t<Args>...> { args... }) }
157  {
158  }
159 
160  template<
161  typename Head,
162  typename... Rest,
163  typename = std::enable_if_t<
164  !std::is_base_of<QObject, std::remove_pointer_t<std::decay_t<Head>>>::value
165  >
166  >
167  WorkerThread (const Head& head, const Rest&... rest)
168  : WorkerThread { static_cast<QObject*> (nullptr), head, rest... }
169  {
170  }
171 
173  {
174  if (!IsAutoQuit_)
175  return;
176 
177  quit ();
178  wait (QuitWait_);
179 
180  if (isRunning ())
181  qWarning () << Q_FUNC_INFO
182  << "thread is still running";
183  }
184 
185  void SetAutoQuit (bool autoQuit)
186  {
187  IsAutoQuit_ = autoQuit;
188  }
189 
190  void SetQuitWait (unsigned long wait)
191  {
192  QuitWait_ = wait;
193  }
194 
196 
197  template<typename F, typename... Args>
198  QFuture<std::result_of_t<F (WorkerType*, Args...)>> ScheduleImpl (F f, Args&&... args)
199  {
200  const auto fWrapped = [f, this] (auto... args) mutable { return std::invoke (f, Worker_.get (), args...); };
201  return WorkerThreadBase::ScheduleImpl (fWrapped, std::forward<Args> (args)...);
202  }
203  protected:
204  void Initialize () override
205  {
206  Worker_ = Initializer_->Initialize ();
207 
208  Initializer_.reset ();
209  }
210 
211  void Cleanup () override
212  {
213  Worker_.reset ();
214  }
215  };
216 }
217 }
WorkerThread(const Head &head, const Rest &... rest)
WorkerThread(QObject *parent=nullptr)
void Initialize() override
void SetAutoQuit(bool autoQuit)
Initializer(std::tuple< Args... > &&tuple)
void SetQuitWait(unsigned long wait)
#define UTIL_THREADS_API
Definition: threadsconfig.h:37
WorkerThread(QObject *parent, const Args &... args)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:955
std::unique_ptr< WorkerType > Worker_
std::unique_ptr< detail::InitializerBase< WorkerType > > Initializer_
QFuture< std::result_of_t< F(WorkerType *, Args...)> > ScheduleImpl(F f, Args &&... args)
QFuture< std::result_of_t< F()> > ScheduleImpl(F func)
QFuture< std::result_of_t< F(Args...)> > ScheduleImpl(F f, Args &&... args)
std::tuple< Args... > Args_
std::unique_ptr< WorkerType > Initialize() override
Definition: constants.h:35
std::unique_ptr< WorkerType > Initialize() override