64 std::function<void(
void *)> m_handle;
65 std::function<void(
void *)> m_handleProxy;
67 std::function<void(
void)> m_handleV;
68 std::function<void(
void)> m_handleVProxy;
70 bool m_dasyncDestroyed =
false;
74 void setDAsyncDestroyed() { m_dasyncDestroyed =
true; }
75 bool dasyncDestroyed() {
return m_dasyncDestroyed; }
82 Q_ASSERT(qApp->instance() && qApp->instance()->thread());
83 moveToThread(qApp->instance()->thread());
85 bool isStartInMain = D_THREAD_IN_MAIN();
87 QObject::connect(
this,
88 &MainWorker::sigRunInMain,
90 &MainWorker::slotRunInMain,
91 isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection);
93 QObject::connect(
this,
94 &MainWorker::sigRunInMainVoid,
96 &MainWorker::slotRunInMainVoid,
97 isStartInMain ? Qt::AutoConnection : Qt::BlockingQueuedConnection);
101 template <
typename FUNC,
typename ArgType>
102 typename std::enable_if<!std::is_void<ArgType>::value>::type setHandle(FUNC &&func)
104 m_handle = [&](
void *arg) {
106 while (q && q->size()) {
112 m_handleProxy = [
this](
void *arg) {
120 template <
typename FUNC,
typename ArgType>
121 typename std::enable_if<std::is_void<ArgType>::value>::type setHandle(FUNC &&func)
123 m_handleV = [&](void) {
128 m_handleVProxy = [
this](void) {
135 void sigRunInMain(
void *arg);
136 void sigRunInMainVoid();
138 void slotRunInMain(
void *arg)
140 Q_ASSERT(D_THREAD_IN_MAIN());
141 if (m_handleProxy && !m_dasyncDestroyed) {
145 void slotRunInMainVoid(
void)
147 Q_ASSERT(D_THREAD_IN_MAIN());
148 if (m_handleVProxy && !m_dasyncDestroyed) {
178class D_DECL_DEPRECATED
DAsync :
public QObject
183 std::condition_variable m_cvIn;
185 std::mutex m_mtxForWaitTask;
186 std::condition_variable m_cvForWaitTask;
193 bool m_dasDestructed =
false;
196 bool destructed() {
return m_dasDestructed; }
197 void setDestructed() { m_dasDestructed =
true; }
200 explicit Guard(
DAsync *as) noexcept
203 m_as->m_status.setFlag(DAsyncState::Ready);
204 m_as->m_status.setFlag(DAsyncState::Finished,
false);
211 m_as->m_threadGuard =
nullptr;
212 m_as->m_status.setFlag(DAsyncState::Finished);
213 m_as->m_status.setFlag(DAsyncState::Ready,
false);
214 if (m_as->m_status.testFlag(DAsyncState::WaitFinished)) {
215 m_as->m_cvForWaitTask.notify_one();
219 void setPending(
bool isPending)
222 m_as->m_status.setFlag(DAsyncState::Pending, isPending);
226 Guard *m_threadGuard =
nullptr;
234 template <
typename T,
typename Enable =
void>
240 struct DataQueueType<T, typename std::enable_if<std::is_void<T>::value>::type>
243 using DataInQueue = DataQueueType<DataTypeIn>;
244 using DataOutQueue = DataQueueType<DataTypeOut>;
246 DataInQueue m_QueueIn;
247 DataOutQueue m_QueueOut;
250 template <
typename T1,
typename T2,
typename Enable1 =
void,
typename Enable2 =
void>
254 template <
typename T1,
typename T2>
257 typename std::enable_if<std::is_void<T1>::value>::type,
258 typename std::enable_if<std::is_void<T2>::value>::type>
260 std::function<void(
void)> cbp;
262 template <
typename T1,
typename T2>
265 typename std::enable_if<!std::is_void<T1>::value>::type,
266 typename std::enable_if<!std::is_void<T2>::value>::type>
268 std::function<T2(T1)> cbp;
270 template <
typename T1,
typename T2>
273 typename std::enable_if<std::is_void<T1>::value>::type,
274 typename std::enable_if<!std::is_void<T2>::value>::type>
276 std::function<T2(
void)> cbp;
278 template <
typename T1,
typename T2>
281 typename std::enable_if<!std::is_void<T1>::value>::type,
282 typename std::enable_if<std::is_void<T2>::value>::type>
284 std::function<void(T1)> cbp;
287 std::mutex m_mtxFunc;
288 FuncType<DataTypeIn, DataTypeOut> m_func GUARDED_BY(m_mtxFunc);
289 DAsyncState::AsyncTaskStatus m_status;
292 explicit DAsync(QObject *parent =
nullptr) noexcept
295 , m_status(DAsyncState::NotReady)
298 m_helper =
new Helper(
this,
this);
303 m_threadGuard->setDestructed();
305 m_status.setFlag(DAsyncState::Cancel);
306 if (m_status.testFlag(DAsyncState::Pending)) {
310 m_mainWorker->setDAsyncDestroyed();
311 m_mainWorker->deleteLater();
312 m_mainWorker =
nullptr;
318 template <
typename PostInType,
typename EmitInType>
319 typename std::enable_if<std::is_void<PostInType>::value && std::is_void<EmitInType>::value>::type emitHelper()
322 Q_EMIT m_mainWorker->sigRunInMainVoid();
325 template <
typename PostInType,
typename EmitInType>
326 typename std::enable_if<!std::is_void<PostInType>::value && !std::is_void<EmitInType>::value>::type emitHelper()
328 m_QueueOut.m_queue.enqueue(m_func.cbp(m_QueueIn.m_queue.dequeue()));
329 Q_EMIT m_mainWorker->sigRunInMain(
static_cast<void *
>(&(m_QueueOut.m_queue)));
332 template <
typename PostInType,
typename EmitInType>
333 typename std::enable_if<!std::is_void<PostInType>::value && std::is_void<EmitInType>::value>::type emitHelper()
335 m_func.cbp(m_QueueIn.m_queue.dequeue());
336 Q_EMIT m_mainWorker->sigRunInMainVoid();
339 template <
typename PostInType,
typename EmitInType>
340 typename std::enable_if<std::is_void<PostInType>::value && !std::is_void<EmitInType>::value>::type emitHelper()
342 m_QueueOut.m_queue.enqueue(m_func.cbp());
343 Q_EMIT m_mainWorker->sigRunInMain(
static_cast<void *
>(&(m_QueueOut.m_queue)));
349 if (m_status.testFlag(DAsyncState::Cancel)) {
356 m_status.setFlag(DAsyncState::Cancel);
357 if (m_status.testFlag(DAsyncState::Pending)) {
361 bool isFinished() {
return m_status.testFlag(DAsyncState::Finished); }
373 void waitForFinished(
bool cancelAllWorks =
true)
375 Q_ASSERT(!D_THREAD_IN_MAIN());
376 if (cancelAllWorks) {
379 if (!m_status.testFlag(DAsyncState::Finished)) {
380 if (m_status.testFlag(DAsyncState::Pending)) {
383 m_status.setFlag(DAsyncState::WaitFinished);
384 std::unique_lock<std::mutex> lck(m_mtxForWaitTask);
385 m_cvForWaitTask.wait(lck);
389 template <
typename FUNC,
typename InputType = DataTypeIn>
390 typename std::enable_if<!std::is_void<InputType>::value, Helper *>::type post(FUNC &&func)
392 m_func.cbp = std::forward<FUNC>(func);
396 m_postProxy = [
this]() {
397 std::thread thread([
this] {
398 if (m_status.testFlag(DAsyncState::Cancel)) {
402 m_threadGuard = &guard;
404 std::unique_lock<std::mutex> lck(m_mtxIn);
406 while (!m_status.testFlag(DAsyncState::Ready) || !m_QueueIn.m_queue.size()) {
407 guard.setPending(
true);
409 m_cvIn.wait_for(lck, std::chrono::milliseconds(200));
410 if (guard.destructed() || m_status.testFlag(DAsyncState::Cancel)) {
414 guard.setPending(
false);
416 while (m_func.cbp && m_QueueIn.m_queue.size()) {
417 emitHelper<DataTypeIn, DataTypeOut>();
427 template <
typename FUNC,
typename InputType = DataTypeIn>
428 typename std::enable_if<std::is_void<InputType>::value, Helper *>::type post(FUNC &&func)
431 std::lock_guard<std::mutex> lckFunc(m_mtxFunc);
432 m_func.cbp = std::forward<FUNC>(func);
437 m_postProxy = [
this]() {
438 std::thread thread([
this] {
439 if (m_status.testFlag(DAsyncState::Cancel)) {
443 m_threadGuard = &guard;
445 std::unique_lock<std::mutex> lck(m_mtxIn);
447 if (!m_status.testFlag(DAsyncState::Ready)) {
448 guard.setPending(
true);
450 m_cvIn.wait_for(lck, std::chrono::milliseconds(200));
451 if (guard.destructed() || m_status.testFlag(DAsyncState::Cancel)) {
455 guard.setPending(
false);
458 std::lock_guard<std::mutex> lckFunc(m_mtxFunc);
459 emitHelper<DataTypeIn, DataTypeOut>();
460 m_func.cbp =
nullptr;
471 template <
typename InputType = DataTypeIn>
472 typename std::enable_if<!std::is_void<InputType>::value>::type postData(
const InputType &data)
474 if (Q_UNLIKELY(!m_status.testFlag(DAsyncState::Cancel))) {
475 m_QueueIn.m_queue.enqueue(data);
476 if (m_status.testFlag(DAsyncState::Pending)) {
483 std::function<void()> m_postProxy;
484 class Helper :
public QObject
489 explicit Helper(
DAsync *async, QObject *parent =
nullptr) noexcept
495 template <
typename FUNC>
496 Helper *then(FUNC &&func)
498 m_async->m_mainWorker->template setHandle<FUNC, DataTypeOut>(std::forward<FUNC>(func));
502 void start(
bool immediately =
true)
504 if (m_async->m_postProxy) {
505 m_async->m_postProxy();
508 m_async->m_status.setFlag(DAsyncState::Ready,
false);
510 m_async->m_status.setFlag(DAsyncState::Ready);
511 if (m_async->m_status.testFlag(DAsyncState::Pending)) {
512 m_async->m_cvIn.notify_one();
518 Helper *m_helper =
nullptr;