LeechCraft  0.6.70-18450-gabe19ee3b0
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>
39  {
40  QFutureInterface<std::invoke_result_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::invoke_result_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  unsigned long QuitWait_ = 2000;
116  protected:
117  using W = WorkerType;
118 
119  std::unique_ptr<WorkerType> Worker_;
120 
121  std::unique_ptr<detail::InitializerBase<WorkerType>> Initializer_;
122  public:
123  WorkerThread (QObject *parent = nullptr)
124  : WorkerThreadBase { parent }
125  , Initializer_ { std::make_unique<detail::Initializer<WorkerType>> () }
126  {
127  }
128 
129  template<typename... Args>
130  WorkerThread (QObject *parent, const Args&... args)
131  : WorkerThreadBase { parent }
132  , Initializer_ { std::make_unique<detail::Initializer<WorkerType, std::decay_t<Args>...>> (std::tuple<std::decay_t<Args>...> { args... }) }
133  {
134  }
135 
136  template<
137  typename Head,
138  typename... Rest,
139  typename = std::enable_if_t<
140  !std::is_base_of<QObject, std::remove_pointer_t<std::decay_t<Head>>>::value
141  >
142  >
143  WorkerThread (const Head& head, const Rest&... rest)
144  : WorkerThread { static_cast<QObject*> (nullptr), head, rest... }
145  {
146  }
147 
149  {
150  quit ();
151  wait (QuitWait_);
152 
153  if (isRunning ())
154  qWarning () << Q_FUNC_INFO
155  << "thread is still running";
156  }
157 
158  void SetQuitWait (unsigned long wait)
159  {
160  QuitWait_ = wait;
161  }
162 
164 
165  template<typename F, typename... Args>
166  QFuture<std::invoke_result_t<F, WorkerType*, Args...>> ScheduleImpl (F f, Args&&... args)
167  {
168  const auto fWrapped = [f, this] (auto... args) mutable { return std::invoke (f, Worker_.get (), args...); };
169  return WorkerThreadBase::ScheduleImpl (fWrapped, std::forward<Args> (args)...);
170  }
171  protected:
172  void Initialize () override
173  {
174  Worker_ = Initializer_->Initialize ();
175 
176  Initializer_.reset ();
177  }
178 
179  void Cleanup () override
180  {
181  Worker_.reset ();
182  }
183  };
184 }
WorkerThread(const Head &head, const Rest &... rest)
WorkerThread(QObject *parent=nullptr)
void Initialize() override
Initializer(std::tuple< Args... > &&tuple)
void SetQuitWait(unsigned long wait)
#define UTIL_THREADS_API
Definition: threadsconfig.h:16
QFuture< std::invoke_result_t< F, WorkerType *, Args... > > ScheduleImpl(F f, Args &&... args)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptrs... > > tuple
Definition: oral.h:1086
WorkerThread(QObject *parent, const Args &... args)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:1083
std::unique_ptr< WorkerType > Worker_
std::unique_ptr< detail::InitializerBase< WorkerType > > Initializer_
QFuture< std::invoke_result_t< F > > ScheduleImpl(F func)
std::tuple< Args... > Args_
std::unique_ptr< WorkerType > Initialize() override
QFuture< std::invoke_result_t< F, Args... > > ScheduleImpl(F f, Args &&... args)
std::unique_ptr< WorkerType > Initialize() override