LeechCraft  0.6.70-10870-g558588d6ec
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 LeechCraft
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 () override 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  protected:
140  using W = WorkerType;
141 
142  std::unique_ptr<WorkerType> Worker_;
143 
144  std::unique_ptr<detail::InitializerBase<WorkerType>> Initializer_;
145  public:
146  WorkerThread (QObject *parent = nullptr)
147  : WorkerThreadBase { parent }
148  , Initializer_ { std::make_unique<detail::Initializer<WorkerType>> () }
149  {
150  }
151 
152  template<typename... Args>
153  WorkerThread (QObject *parent, const Args&... args)
154  : WorkerThreadBase { parent }
155  , Initializer_ { std::make_unique<detail::Initializer<WorkerType, std::decay_t<Args>...>> (std::tuple<std::decay_t<Args>...> { args... }) }
156  {
157  }
158 
159  template<
160  typename Head,
161  typename... Rest,
162  typename = std::enable_if_t<
163  !std::is_base_of<QObject, std::remove_pointer_t<std::decay_t<Head>>>::value
164  >
165  >
166  WorkerThread (const Head& head, const Rest&... rest)
167  : WorkerThread { static_cast<QObject*> (nullptr), head, rest... }
168  {
169  }
170 
172  {
173  if (!IsAutoQuit_)
174  return;
175 
176  quit ();
177  wait (2000);
178 
179  if (isRunning ())
180  qWarning () << Q_FUNC_INFO
181  << "thread is still running";
182  }
183 
185 
186  void SetAutoQuit (bool autoQuit)
187  {
188  IsAutoQuit_ = autoQuit;
189  }
190 
191  template<typename F, typename... Args>
192  QFuture<std::result_of_t<F (WorkerType*, Args...)>> ScheduleImpl (F f, Args&&... args)
193  {
194  const auto fWrapped = [f, this] (auto... args) mutable { return std::invoke (f, Worker_.get (), args...); };
195  return WorkerThreadBase::ScheduleImpl (fWrapped, std::forward<Args> (args)...);
196  }
197  protected:
198  void Initialize () override
199  {
200  Worker_ = Initializer_->Initialize ();
201 
202  Initializer_.reset ();
203  }
204 
205  void Cleanup () override
206  {
207  Worker_.reset ();
208  }
209  };
210 }
211 }
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:931
WorkerThread(QObject *parent, const Args &... args)
#define UTIL_THREADS_API
Definition: threadsconfig.h:37
WorkerThread(QObject *parent=nullptr)
QFuture< std::result_of_t< F(Args...)> > ScheduleImpl(F f, Args &&... args)
QFuture< std::result_of_t< F(WorkerType *, Args...)> > ScheduleImpl(F f, Args &&... args)
std::unique_ptr< WorkerType > Initialize() override
std::unique_ptr< WorkerType > Worker_
QFuture< std::result_of_t< F()> > ScheduleImpl(F func)
Initializer(std::tuple< Args... > &&tuple)
std::unique_ptr< detail::InitializerBase< WorkerType > > Initializer_
WorkerThread(const Head &head, const Rest &... rest)
std::unique_ptr< WorkerType > Initialize() override