1 /**************************************************************************** 2 ** 3 ** DQt - D bindings for the Qt Toolkit 4 ** 5 ** GNU Lesser General Public License Usage 6 ** This file may be used under the terms of the GNU Lesser 7 ** General Public License version 3 as published by the Free Software 8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 9 ** packaging of this file. Please review the following information to 10 ** ensure the GNU Lesser General Public License version 3 requirements 11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 12 ** 13 ****************************************************************************/ 14 module qt.core.thread; 15 extern(C++): 16 17 import core.stdc.config; 18 import qt.config; 19 import qt.core.coreapplication; 20 import qt.core.coreevent; 21 import qt.core.deadlinetimer; 22 import qt.core.namespace; 23 import qt.core.object; 24 import qt.helpers; 25 26 // For QThread::create. The configure-time test just checks for the availability 27 // of std::future and std::async; for the C++17 codepath we perform some extra 28 // checks here (for std::invoke and C++14 lambdas). 29 /+ #if QT_CONFIG(cxx11_future) 30 # if defined(__cpp_lib_invoke) && __cpp_lib_invoke >= 201411 \ 31 && defined(__cpp_init_captures) && __cpp_init_captures >= 201304 \ 32 && defined(__cpp_generic_lambdas) && __cpp_generic_lambdas >= 201304 33 # define QTHREAD_HAS_VARIADIC_CREATE 34 # endif 35 #endif +/ 36 37 38 39 extern(C++, class) struct QThreadData; 40 extern(C++, class) struct QThreadPrivate; 41 /+ class QAbstractEventDispatcher; +/ 42 43 class /+ Q_CORE_EXPORT +/ QThread : QObject 44 { 45 mixin(Q_OBJECT); 46 public: 47 static /+ Qt:: +/qt.core.namespace.HANDLE currentThreadId()/+ noexcept /+ Q_DECL_PURE_FUNCTION +/__attribute__((pure))+/; 48 static QThread currentThread(); 49 static int idealThreadCount()/+ noexcept+/; 50 static void yieldCurrentThread(); 51 52 /+ explicit +/this(QObject parent = null); 53 ~this(); 54 55 enum Priority { 56 IdlePriority, 57 58 LowestPriority, 59 LowPriority, 60 NormalPriority, 61 HighPriority, 62 HighestPriority, 63 64 TimeCriticalPriority, 65 66 InheritPriority 67 } 68 69 final void setPriority(Priority priority); 70 final Priority priority() const; 71 72 final bool isFinished() const; 73 final bool isRunning() const; 74 75 final void requestInterruption(); 76 final bool isInterruptionRequested() const; 77 78 final void setStackSize(uint stackSize); 79 final uint stackSize() const; 80 81 final void exit(int retcode = 0); 82 83 final QAbstractEventDispatcher* eventDispatcher() const; 84 final void setEventDispatcher(QAbstractEventDispatcher* eventDispatcher); 85 86 override bool event(QEvent event); 87 final int loopLevel() const; 88 89 /+ #ifdef Q_CLANG_QDOC 90 template <typename Function, typename... Args> 91 static QThread *create(Function &&f, Args &&... args); 92 template <typename Function> 93 static QThread *create(Function &&f); 94 #else 95 # if QT_CONFIG(cxx11_future) 96 # ifdef QTHREAD_HAS_VARIADIC_CREATE +/ 97 static if(defined!"QTHREAD_HAS_VARIADIC_CREATE") 98 { 99 /+ template <typename Function, typename... Args> +/ 100 /+ static QThread *create(Function &&f, Args &&... args); +/ 101 } 102 else 103 { 104 /+ # else +/ 105 /+ template <typename Function> +/ 106 /+ static QThread *create(Function &&f); +/ 107 } 108 /+ # endif // QTHREAD_HAS_VARIADIC_CREATE 109 # endif // QT_CONFIG(cxx11_future) 110 #endif +/ // Q_CLANG_QDOC 111 112 public /+ Q_SLOTS +/: 113 @QSlot final void start(Priority = Priority.InheritPriority); 114 @QSlot final void terminate(); 115 @QSlot final void quit(); 116 117 public: 118 final bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer.ForeverConstant.Forever)); 119 // ### Qt6 inline this function 120 final bool wait(cpp_ulong time); 121 122 static void sleep(cpp_ulong ); 123 static void msleep(cpp_ulong ); 124 static void usleep(cpp_ulong ); 125 126 /+ Q_SIGNALS +/public: 127 @QSignal final void started(QPrivateSignal); 128 @QSignal final void finished(QPrivateSignal); 129 130 protected: 131 /+ virtual +/ void run(); 132 final int exec(); 133 134 static void setTerminationEnabled(bool enabled = true); 135 136 protected: 137 this(ref QThreadPrivate dd, QObject parent = null); 138 139 private: 140 /+ Q_DECLARE_PRIVATE(QThread) +/ 141 142 /+ #if QT_CONFIG(cxx11_future) +/ 143 /+ static QThread *createThreadImpl(std::future<void> &&future); +/ 144 /+ #endif +/ 145 146 /+ friend class QCoreApplication; +/ 147 /+ friend class QThreadData; +/ 148 } 149 150 /+ #if QT_CONFIG(cxx11_future) +/ 151 152 /+ #if defined(QTHREAD_HAS_VARIADIC_CREATE) || defined(Q_CLANG_QDOC) 153 // C++17: std::thread's constructor complying call 154 template <typename Function, typename... Args> 155 QThread *QThread::create(Function &&f, Args &&... args) 156 { 157 using DecayedFunction = typename std::decay<Function>::type; 158 auto threadFunction = 159 [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void 160 { 161 (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...); 162 }; 163 164 return createThreadImpl(std::async(std::launch::deferred, 165 std::move(threadFunction), 166 std::forward<Args>(args)...)); 167 } 168 #elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304 169 // C++14: implementation for just one callable 170 template <typename Function> 171 QThread *QThread::create(Function &&f) 172 { 173 using DecayedFunction = typename std::decay<Function>::type; 174 auto threadFunction = 175 [f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void 176 { 177 (void)f(); 178 }; 179 180 return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction))); 181 } 182 #else +/ 183 static if(!defined!"QTHREAD_HAS_VARIADIC_CREATE") 184 { 185 // C++11: same as C++14, but with a workaround for not having generalized lambda captures 186 } 187 extern(C++, "QtPrivate") { 188 struct Callable(Function) 189 { 190 /+ explicit Callable(Function &&f) 191 : m_function(std::forward<Function>(f)) 192 { 193 } +/ 194 195 // Apply the same semantics of a lambda closure type w.r.t. the special 196 // member functions, if possible: delete the copy assignment operator, 197 // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure]) 198 /+ ~Callable() = default; +/ 199 /+ Callable(const Callable &) = default; +/ 200 /+ Callable(Callable &&) = default; +/ 201 /+ref Callable operator =(ref const(Callable) ) /+ = delete +/;+/ 202 /+ Callable &operator=(Callable &&) = default; +/ 203 204 /+void operator ()() 205 { 206 cast(void)m_function(); 207 }+/ 208 209 /+ typename std::decay<Function>::type +/decay.type m_function; 210 } 211 } 212 static if(!defined!"QTHREAD_HAS_VARIADIC_CREATE") 213 { 214 // namespace QtPrivate 215 216 /+ template <typename Function> 217 QThread *QThread::create(Function &&f) 218 { 219 return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f)))); 220 } +/ 221 } 222 /+ #endif +/ // QTHREAD_HAS_VARIADIC_CREATE 223 224 /+ #endif +/ // QT_CONFIG(cxx11_future) 225