ThreadWeaver

thread.cpp
1 /* -*- C++ -*-
2  This file is part of ThreadWeaver. It implements the Thread class.
3 
4  SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 
8  $Id: Thread.cpp 25 2005-08-14 12:41:38Z mirko $
9 */
10 
11 #include "thread.h"
12 
13 #include <QCoreApplication>
14 #include <QDebug>
15 #include <QPointer>
16 
17 #include "debuggingaids.h"
18 #include "exception.h"
19 #include "job.h"
20 #include "threadweaver.h"
21 #include "weaver.h"
22 
23 using namespace ThreadWeaver;
24 
25 class Q_DECL_HIDDEN Thread::Private
26 {
27 public:
28  explicit Private(Weaver *theParent)
29  : parent(theParent)
30  , id(makeId())
31  , job(nullptr)
32  {
33  Q_ASSERT(parent);
34  }
35 
36  Weaver *parent;
37  const unsigned int id;
38  JobPointer job;
39  QMutex mutex;
40 
41  static unsigned int makeId()
42  {
43  static QAtomicInt s_id(1);
44  return s_id.fetchAndAddRelease(1);
45  }
46 };
47 
49  : QThread() // no parent, because the QObject hierarchy of this thread
50  // does not have a parent (see QObject::pushToThread)
51  , d(new Private(parent))
52 {
53  const QString queueName =
54  parent->objectName().isEmpty() ? QString::fromLatin1("Queue(0x%1)").arg(quintptr(parent), 0, 16, QChar::fromLatin1('0')) : parent->objectName();
55  setObjectName(QString::fromLatin1("%1[%2]").arg(queueName).arg(QString::number(id()), 2, QChar::fromLatin1('0')));
56 }
57 
59 {
60  delete d;
61 }
62 
63 unsigned int Thread::id() const
64 {
65  return d->id; // id is const
66 }
67 
69 {
70  Q_ASSERT(d->parent);
71  Q_ASSERT(QCoreApplication::instance() != nullptr);
72  d->parent->threadEnteredRun(this);
73 
74 #if THREADWEAVER_BUILD_DEPRECATED_SINCE(5, 80)
75  Q_EMIT started(this);
76 #endif
77 
78  TWDEBUG(3, "Thread::run [%u]: running.\n", id());
79 
80  bool wasBusy = false;
81  while (true) {
82  TWDEBUG(3, "Thread::run [%u]: trying to execute the next job.\n", id());
83 
84  try {
85  // the assignment is intentional: newJob needs to go out of scope at the end of the if statement
86  if (JobPointer newJob = d->parent->applyForWork(this, wasBusy)) {
87  QMutexLocker l(&d->mutex);
88  Q_UNUSED(l);
89  d->job = newJob;
90  } else {
91  break;
92  }
93  } catch (AbortThread &) {
94  break;
95  }
96 
97  wasBusy = true;
98  d->job->execute(d->job, this);
99  JobPointer oldJob;
100  { // When finally destroying the last reference to d->job, do not hold the mutex.
101  // It may trigger destruction of the job, which can execute arbitrary code.
102  QMutexLocker l(&d->mutex);
103  Q_UNUSED(l);
104  oldJob = d->job;
105  d->job.clear();
106  }
107  oldJob.clear();
108  }
109  TWDEBUG(3, "Thread::run [%u]: exiting.\n", id());
110 }
111 
113 {
114  QMutexLocker l(&d->mutex);
115  Q_UNUSED(l);
116  if (d->job) {
117  d->job->requestAbort();
118  }
119 }
void run() override
The run method is reimplemented to execute jobs from the queue.
Definition: thread.cpp:68
QString number(int n, int base)
Q_EMITQ_EMIT
void started()
A Weaver manages worker threads.
Definition: weaver.h:34
~Thread() override
The destructor.
Definition: thread.cpp:58
Thread(Weaver *parent=nullptr)
Create a thread.
Definition: thread.cpp:48
QCoreApplication * instance()
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLatin1(const char *str, int size)
Thread represents a worker thread in a Queue's inventory.
Definition: thread.h:27
void requestAbort()
Request the abortion of the job that is processed currently.
Definition: thread.cpp:112
QObject * parent() const const
unsigned int id() const
Returns the thread id.
Definition: thread.cpp:63
QChar fromLatin1(char c)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:09:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.