LeechCraft  0.6.70-15082-g543737046d
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  * 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 
22 namespace 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>
79  struct InitializerBase
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>
113  class WorkerThread : public WorkerThreadBase
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 
149  ~WorkerThread ()
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 }
QList
Definition: ianrulesstorage.h:14
UTIL_THREADS_API
#define UTIL_THREADS_API
Definition: threadsconfig.h:16
LC::Util
Definition: icoreproxy.h:33
LC::Util::WorkerThreadBase::ScheduleImpl
QFuture< std::result_of_t< F()> > ScheduleImpl(F func)
Definition: workerthreadbase.h:50
LC::Util::WorkerThread
Definition: workerthreadbase.h:119
futures.h
LC::Util::WorkerThreadBase
Definition: workerthreadbase.h:30
LC::Util::detail::Initializer
Definition: workerthreadbase.h:93
QFuture
Definition: idownload.h:17
LC::Util::oral::sph::f
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:952
QFutureInterface
Definition: consistencychecker.h:20
threadsconfig.h
LC::Util::Head
Definition: typelist.h:35
LC::Util::detail::InitializerBase
Definition: workerthreadbase.h:85