KEMBAR78
Qt Multi-threading Guide | PDF | Thread (Computing) | Queue (Abstract Data Type)
0% found this document useful (0 votes)
222 views70 pages

Qt Multi-threading Guide

The document discusses multi-threading support in Qt. It provides an overview of Qt classes that enable threading like QThread, QMutex, QWaitCondition, and QSemaphore. It describes concepts like thread affinity, posted events, signals and slots. It also covers new features in Qt 4.3 like BlockingQueuedConnection and posted event priorities.

Uploaded by

aanvanbasten
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
222 views70 pages

Qt Multi-threading Guide

The document discusses multi-threading support in Qt. It provides an overview of Qt classes that enable threading like QThread, QMutex, QWaitCondition, and QSemaphore. It describes concepts like thread affinity, posted events, signals and slots. It also covers new features in Qt 4.3 like BlockingQueuedConnection and posted event priorities.

Uploaded by

aanvanbasten
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 70

Multi-threading in Qt Bradley T Hughes

Introduction

Bradley T Hughes

Joined Trolltech in May, 2000 Senior Software Engineer Team Lead for the Qt Platform Team Open Source Programmer

Agenda

Introduction Thread Support Overview Classes Concepts New in 4.3 and 4.4

Thread Support in Qt

What can I do with Qt?


Platform independent multi-threading Start threads Synchronize threads Store per-thread data

Thread Support in Qt

Qt provides much more...


Thread-affinity in QObject Per-thread event loops Post events to any thread Signals and slots across threads Thread-safe reference counting

Agenda

Introduction Thread Support Overview Classes Concepts New in 4.3 and 4.4

Classes

QThread

Abstract class Must reimplement 'void run()' void start() bool wait(ulong timeout) void terminate() - DO NOT USE bool isFinished() bool isRunning()

Classes

QThread

QObject subclass SIGNAL(started()) SIGNAL(finished()) SIGNAL(terminated()) Per-thread event loop int exec() SLOT(quit())

Examples class MyThread : public QThread { Q_OBJECT public: void run() { // do some work } };
9

Examples void MyClass::startThread() { myThread = new MyThread; connect(myThread, SIGNAL(finished()), SLOT(threadFinished())); thread->start(); }

10

Examples void MyClass::threadFinished() { // myThread is finished ... // cleanup delete myThread; myThread = 0; }
11

Classes

QMutex

Mutual-exclusion primitive Recursive and non-recursive (default) modes void lock(), bool tryLock() void unlock()

12

Examples void MyQueue::queueNew() { // protect data, not code mutex.lock(); Entity *entity = cache.isEmpty() ? new Entity : cache.takeFirst(); queue.append(entity); mutex.unlock(); }
13

Classes

QMutexLocker

Uses RAII Automatically lock/unlock a QMutex void unlock(), void relock() Starting with Qt 4.2, keeps state Destructor does not unlock if you call unlock()

14

Examples void MyQueue::queueNew() { QMutexLocker locker(&mutex); Entity *entity = cache.isEmpty() ? new Entity : cache.takeFirst(); queue.append(entity); }
15

Examples void MyClass::complexFunction() { QMutexLocker locker(&mutex); if (...) return; // unlocked try { ... } catch { ... throw; // unlocked } } // unlocked

16

Classes

QWaitCondition

Condition variable Thread waits until told to continue Used together with non-recursive QMutexes bool wait(QMutex *, ulong timeout) void wakeOne(), void wakeAll()

17

Examples Entity *MyQueue::dequeue() { QMutexLocker locker(&mutex); while (queue.isEmpty()) waitCondition.wait(&mutex); return queue.takeFirst(); }

18

Examples void MyQueue::queueNew() { QMutexLocker locker(&mutex); Entity *entity = cache.isEmpty() ? new Entity : cache.takeFirst(); queue.append(entity); waitCondition.wakeOne(); }
19

Classes

QSemaphore

Simple counting semaphore Constructor initializes available resources void acquire(int), bool tryAcquire(int) void release(int) int available()

20

Examples void Producer::run() { for(int i = 0; i < DataSize; ++i) { freeBytes.acquire(); buffer[i] = qrand()%4; usedBytes.release(); } }
21

Examples void Consumer::run() { for(int i = 0; i < DataSize; ++i) { usedBytes.acquire(); file.write(buffer[i]); freeBytes.release(); } }
22

Classes

QReadWriteLock

Shared-exclusive lock Multiple readers, single writer void lockForRead(), bool tryLockForRead() void lockForWrite(), bool tryLockForWrite() void unlock()

23

Examples bool MyQueue::find(Entity *e) { bool found = false; readWriteLock.lockForRead(); foreach (Entity *q, queue){ if (found = (q == e)) break; } readWriteLock.unlock(); return found; }

24

Examples void MyQueue::queueNew() { readWriteLock.lockForWrite(); Entity *entity = cache.isEmpty() ? new Entity : cache.takeFirst(); queue.append(entity); readWriteLock.unlock(); }
25

Classes

QReadLocker and QWriteLocker


RAII again This time on QReadWriteLock void unlock(), void relock() Starting with 4.2, also keeps state

26

Examples bool MyQueue::find(Entity *e) { QReadLocker locker(&lock); foreach (Entity *q, queue){ if (q == e) return true; } return false; }
27

Examples void MyQueue::queueNew() { QWriteLocker locker(&lock); Entity *entity = cache.isEmpty() ? new Entity : cache.takeFirst(); queue.append(entity); }
28

Classes

QThreadStorage

Typesafe per-thread data storage Data deleted when thread exits bool hasLocalData() T localData(), void setLocalData(T) Stores points to data

Store by value? Partial template specialization not supported in MSVC 6.0, .NET 2002

29

Examples QThreadStorage<Queue *> cache; void MyQueue::done(Entity *e) { if (!cache.hasLocalData()) { Queue *q = new Queue; cache.setLocalData(q); } cache.localData()->append(e); }
30

Examples void MyQueue::queueNew() { Queue *c = cache.localData(); Entity *entity = (!c || c->isEmpty()) ? new Entity : c->takeFirst(); QMutexLocker locker(&mutex); queue.append(entity); }
31

Agenda

Introduction Thread Support Overview Classes Concepts New in 4.3 and 4.4

32

Concepts

Thread affinity in QObject


Object belongs to a thread That thread delivers events to object Default is the thread that created the object Change with QObject::moveToThread() Per-thread event loops

33

Pop Quiz

What is the thread affinity of QApplication?

34

Pop Quiz int main(int argc, char **argv) { QApplication app(argc, argv); qDebug() << app.thread(); }

35

Pop Quiz

What is the thread affinity of QApplication?

Answer: The main() thread. Qt creates a QThread object that represents the main() thread, so app.thread() returns a valid pointer.

36

Pop Quiz

What's the thread affinity of a QTimer created in a QThread::run() reimplementation?

37

Pop Quiz void MyThread::run() { QTimer timer; qDebug() << timer.thread(); }

38

Pop Quiz

What's the thread affinity of a QTimer created in a QThread::run() reimplementation?

Answer: The MyThread instance. Since run() is called by the new thread context, timer.thread() is the same as the 'this' pointer.

39

Pop Quiz

What is the affinity of a QThread instance?

40

Pop Quiz int main(int argc, char **argv) { QApplication app(argc, argv); QThread thread; qDebug() << thread.thread(); }

41

Pop Quiz

What is the affinity of a QThread instance?

Answer: The main() thread. The QThread instance has affinity to thread that created it, not to itself. In other words, the thread is not responsible for delivering its own events. More on this later...

42

Concepts

Default thread affinity is the current thread Objects associated with thread that created them

Code examples from quiz show this clearly

Of course, thread affinity can be changed...

43

Examples void MyObject::downloadFile() { DlThread *thr = new DlThread; Downloader *dl = new Downloader; // move 'dl' to another thread dl->moveToThread(thr); ...
44

Examples connect(thr,SIGNAL(started()), dl,SLOT(loadDown())); connect(dl,SIGNAL(finished()), thr,SLOT(quit())); connect(thr,SIGNAL(finished()), this,SLOT(loadedDown())); // start downloading thread->start(); }
45

Examples class DlThread : public QThread { Q_OBJECT public: void run() { exec(); } };
46

Concepts

Posted events

QApplication::postEvent() Schedules an event for delivery Different from sendEvent() Threads handle events for their objects

47

Examples void postAnEventTo(QObject *object) { QEvent *event = new QEvent(QEvent::User); QApplication::postEvent(object, event); // event not delivered yet! }

48

Examples bool sendAnEventTo(QObject *object) { QEvent event(QEvent::User); QApplication::sendEvent(object, &event); // event has been delivered return event.isAccepted(); }

49

Concepts

Signals and slots


Communication between objects Qt::ConnectionType Direct: Slots called in context of emitter Queued: Posts an event to receiver Auto: Chooses Direct or Queued based on: Current thread Sender's thread Receiver's thread

50

Examples void MyObject::createSomeObject() { SomeObject *receiver = new SomeObject; connect(this, SIGNAL(signal())), receiver, SLOT(slot())), Qt::QueuedConnection); } void MyObject::emitSignal() { emit signal(); }

51

Examples // Tip: call a slot by name QMetaObject::invokeMethod( object, slot); // Tip: pass an argument QMetaObject::invokeMethod( object, setText, QString(Hello World));
52

Examples // Tip: but not right now QMetaObject::invokeMethod( object, setText, Qt::QueuedConnection, QString(Hello World));

53

Concepts

Implicit sharing

Copy-on-write

All shared classes are implicit All use atomic reference counting

54

Examples void MyThread::run() { QString string; forever { // implicit sharing in action string = readLargeFile(); // just pass a copy emit dataReady(string); } }
55

Examples // atomic ref count != thread-safe! QString string; void MyThread::run() { forever { // WRONG, cannot copy/modify // at the same time string = format(string); } } 56

Examples QMutex mutex; QString string; void MyThread::run() { forever { // RIGHT, protect shared data QMutexLocker locker(&mutex); string = format(string); } } 57

Agenda

Introduction Thread Support Overview Classes Concepts New in 4.3 and 4.4

58

New in 4.3

Qt::BlockingQueuedConnection

New connection type Mostly the same as QueuedConnection But current thread blocks until slot called Should only be used for receivers in a different thread

59

Examples connect( sender, SIGNAL(signal()), receiver, SLOT(slot()), Qt::BlockingQueuedConnection); QMetaObject::invokeMethod( object, methodName, Qt::BlockingQueuedConnection);
60

New in 4.3

Posted event priorities


Numerical priority can be given to any posted event Higher values have higher priority 4 is higher than zero, zero is higher than -2 Convenience enum, Qt::EventPriority Qt::HighEventPriorty = 1 Qt::NormalEventPriority = 0 (default) Qt::LowEventPriority = -1

61

Examples // posted with default priority (0) QApplication::postEvent(r, e1); QApplication::postEvent(r, e2); // higher priority QApplication::postEvent(r, e3, 1); // lower priority QApplication::postEvent(r, e4, -1); // delivery order: e3, e1, e2, e4
62

New in 4.3

Timed try-locking

Blocks current thread for a maximum timeout Returns true if lock acquired, false otherwise QMutex bool tryLock(int timeout) QReadWriteLock bool tryLockForRead(int timeout) bool tryLockForWrite(int timeout) QSemaphore bool tryAcquire(int n, int timeout)

63

Examples // wait for at most 1 second if (mutex.tryLock(1000)) { // got it ... } else { ... }

64

New in 4.3

Recursive write-locking in QReadWriteLock

Thread can lockForWrite() multiple times

QThread::idealThreadCount()

Returns number of CPU cores

QThreadStorage

Refactored to allow an arbitrary number of instances Previously hard-coded to 256

65

New in 4.4 (tentative)

QThread no longer abstract


run() is not pure virtual anymore Default implementation calls exec() Use QThread without subclassing Avoid thread affinity of QThread confusion

66

New in 4.4 (tentative)

Public atomic API

QAtomicInt Atomic operations on integers bool ref(), bool deref() Test-and-set, fetch-and-store, fetch-and-add QAtomicPointer Type-safe atomic pointer operations Test-and-set, fetch-and-store, fetch-and-add Explicit memory ordering semantics Relaxed, acquire, release, ordered Feature test API

67

New in 4.4 (tentative)

Qt Concurrent

Not discussed here Stay put, scheduled immediately after this presentation

68

Agenda

Introduction Thread Support Overview Classes Concepts New in 4.3 and 4.4

69

Thanks!

Any questions?

70

You might also like