summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2017-09-15 17:53:48 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2017-09-24 15:05:25 +0000
commit0d0ad598c54652dbe04d5716025facd83adc979b (patch)
treeb52933ec69fbdcb0bd8a2e684adaf06796ee5815 /src/corelib/thread
parente5033a5c9b769815112e922d0b224af860afd219 (diff)
QThread::create: move implementation out of line
Now that we accept STL datatypes in our ABI, expose a factory function that takes a std::future<void>, and hide the QThread subclass in our implementation. This also solves the problem of a non-exported polymorphic class that would generate duplicate vtables / typeinfo in all TUs. Change-Id: I70a5c301e7c589de1a4a189db39b86b956d1ba0d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qthread.cpp24
-rw-r--r--src/corelib/thread/qthread.h121
2 files changed, 76 insertions, 69 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 1ec626a53b..e3ba1e4449 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const
\sa start()
*/
+#ifdef QTHREAD_HAS_CREATE
+class QThreadCreateThread : public QThread
+{
+public:
+ explicit QThreadCreateThread(std::future<void> &&future)
+ : m_future(std::move(future))
+ {
+ }
+
+private:
+ void run() override
+ {
+ m_future.get();
+ }
+
+ std::future<void> m_future;
+};
+
+QThread *QThread::createThreadImpl(std::future<void> &&future)
+{
+ return new QThreadCreateThread(std::move(future));
+}
+#endif // QTHREAD_HAS_CREATE
+
/*!
\class QDaemonThread
\since 5.5
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 8f87888162..670197d375 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -165,98 +165,81 @@ protected:
private:
Q_DECLARE_PRIVATE(QThread)
+#ifdef QTHREAD_HAS_CREATE
+ static QThread *createThreadImpl(std::future<void> &&future);
+#endif
+
friend class QCoreApplication;
friend class QThreadData;
};
#ifdef QTHREAD_HAS_CREATE
-namespace QtPrivate {
-class QThreadCreateThread : public QThread
+#ifdef QTHREAD_HAS_VARIADIC_CREATE
+// C++17: std::thread's constructor complying call
+template <typename Function, typename... Args>
+QThread *QThread::create(Function &&f, Args &&... args)
{
-public:
-#if defined(QTHREAD_HAS_VARIADIC_CREATE)
- // C++17: std::thread's constructor complying call
- template <typename Function, typename... Args>
- explicit QThreadCreateThread(Function &&f, Args &&... args)
- : m_future(std::async(std::launch::deferred,
- [f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))](auto &&... largs) mutable -> void
- {
- (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
- }, std::forward<Args>(args)...))
- {
- }
-#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
- // C++14: implementation for just one callable
- template <typename Function>
- explicit QThreadCreateThread(Function &&f)
- : m_future(std::async(std::launch::deferred,
- [f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))]() mutable -> void
- {
- (void)f();
- }))
- {
- }
-#else
-private:
- // C++11: same as C++14, but with a workaround for not having generalized lambda captures
- template <typename Function>
- struct Callable
- {
- explicit Callable(Function &&f)
- : m_function(std::forward<Function>(f))
+ using DecayedFunction = typename std::decay<Function>::type;
+ auto threadFunction =
+ [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
{
- }
-
-#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
- // Apply the same semantics of a lambda closure type w.r.t. the special
- // member functions, if possible: delete the copy assignment operator,
- // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
- ~Callable() = default;
- Callable(const Callable &) = default;
- Callable(Callable &&) = default;
- Callable &operator=(const Callable &) = delete;
- Callable &operator=(Callable &&) = default;
-#endif
+ (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
+ };
- void operator()()
+ return createThreadImpl(std::async(std::launch::deferred,
+ std::move(threadFunction),
+ std::forward<Args>(args)...));
+}
+#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
+// C++14: implementation for just one callable
+template <typename Function>
+QThread *QThread::create(Function &&f)
+{
+ using DecayedFunction = typename std::decay<Function>::type;
+ auto threadFunction =
+ [f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
{
- (void)m_function();
- }
+ (void)f();
+ };
- typename std::decay<Function>::type m_function;
- };
-
-public:
- template <typename Function>
- explicit QThreadCreateThread(Function &&f)
- : m_future(std::async(std::launch::deferred, Callable<Function>(std::forward<Function>(f))))
+ return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction)));
+}
+#else
+// C++11: same as C++14, but with a workaround for not having generalized lambda captures
+namespace QtPrivate {
+template <typename Function>
+struct Callable
+{
+ explicit Callable(Function &&f)
+ : m_function(std::forward<Function>(f))
{
}
-#endif // QTHREAD_HAS_VARIADIC_CREATE
-private:
- void run() override
+#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+ // Apply the same semantics of a lambda closure type w.r.t. the special
+ // member functions, if possible: delete the copy assignment operator,
+ // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
+ ~Callable() = default;
+ Callable(const Callable &) = default;
+ Callable(Callable &&) = default;
+ Callable &operator=(const Callable &) = delete;
+ Callable &operator=(Callable &&) = default;
+#endif
+
+ void operator()()
{
- m_future.get();
+ (void)m_function();
}
- std::future<void> m_future;
+ typename std::decay<Function>::type m_function;
};
-
} // namespace QtPrivate
-#ifdef QTHREAD_HAS_VARIADIC_CREATE
-template <typename Function, typename... Args>
-QThread *QThread::create(Function &&f, Args &&... args)
-{
- return new QtPrivate::QThreadCreateThread(std::forward<Function>(f), std::forward<Args>(args)...);
-}
-#else
template <typename Function>
QThread *QThread::create(Function &&f)
{
- return new QtPrivate::QThreadCreateThread(std::forward<Function>(f));
+ return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
}
#endif // QTHREAD_HAS_VARIADIC_CREATE