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>
This commit is contained in:
parent
e5033a5c9b
commit
0d0ad598c5
@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const
|
|||||||
\sa start()
|
\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
|
\class QDaemonThread
|
||||||
\since 5.5
|
\since 5.5
|
||||||
|
@ -165,98 +165,81 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Q_DECLARE_PRIVATE(QThread)
|
Q_DECLARE_PRIVATE(QThread)
|
||||||
|
|
||||||
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
|
static QThread *createThreadImpl(std::future<void> &&future);
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class QCoreApplication;
|
friend class QCoreApplication;
|
||||||
friend class QThreadData;
|
friend class QThreadData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef QTHREAD_HAS_CREATE
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
namespace QtPrivate {
|
|
||||||
|
|
||||||
class QThreadCreateThread : public QThread
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#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()()
|
|
||||||
{
|
|
||||||
(void)m_function();
|
|
||||||
}
|
|
||||||
|
|
||||||
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))))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override
|
|
||||||
{
|
|
||||||
m_future.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<void> m_future;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QtPrivate
|
|
||||||
|
|
||||||
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
||||||
|
// C++17: std::thread's constructor complying call
|
||||||
template <typename Function, typename... Args>
|
template <typename Function, typename... Args>
|
||||||
QThread *QThread::create(Function &&f, Args &&... args)
|
QThread *QThread::create(Function &&f, Args &&... args)
|
||||||
{
|
{
|
||||||
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f), std::forward<Args>(args)...);
|
using DecayedFunction = typename std::decay<Function>::type;
|
||||||
|
auto threadFunction =
|
||||||
|
[f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
|
||||||
|
{
|
||||||
|
(void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
return createThreadImpl(std::async(std::launch::deferred,
|
||||||
|
std::move(threadFunction),
|
||||||
|
std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
|
||||||
|
// C++14: implementation for just one callable
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
QThread *QThread::create(Function &&f)
|
QThread *QThread::create(Function &&f)
|
||||||
{
|
{
|
||||||
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f));
|
using DecayedFunction = typename std::decay<Function>::type;
|
||||||
|
auto threadFunction =
|
||||||
|
[f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
|
||||||
|
{
|
||||||
|
(void)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))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#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()()
|
||||||
|
{
|
||||||
|
(void)m_function();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename std::decay<Function>::type m_function;
|
||||||
|
};
|
||||||
|
} // namespace QtPrivate
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
QThread *QThread::create(Function &&f)
|
||||||
|
{
|
||||||
|
return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
|
||||||
}
|
}
|
||||||
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user