| Home |
This example demonstrates how to use QtSharedMemory to access a block of shared memory between threads.
factory.h:
/****************************************************************************
**
** Copyright (C) 2003-2007 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding a valid Qt Solutions License Agreement may use this
** file in accordance with the rights, responsibilities, and obligations
** contained therein. Please consult your licensing agreement or contact
** [email protected] if any conditions of this licensing are not clear
** to you.
**
** Further information about Qt Solutions licensing is available at:
** http://www.trolltech.com/products/qt/addon/solutions/
** or by contacting [email protected].
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#ifndef FACTORY_H
#define FACTORY_H
#include <QThread>
#include <QList>
#include <qtsharedmemory.h>
class Worker : public QThread {
public:
inline Worker(int count) { cnt = count; }
void run();
private:
int cnt;
};
class Factory
{
public:
Factory(int workers);
~Factory();
void startCounting();
private:
QList<Worker *> workers;
QtSharedMemory sharedMemory;
};
#endif
factory.cpp:
/****************************************************************************
**
** Copyright (C) 2003-2007 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding a valid Qt Solutions License Agreement may use this
** file in accordance with the rights, responsibilities, and obligations
** contained therein. Please consult your licensing agreement or contact
** [email protected] if any conditions of this licensing are not clear
** to you.
**
** Further information about Qt Solutions licensing is available at:
** http://www.trolltech.com/products/qt/addon/solutions/
** or by contacting [email protected].
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "factory.h"
#include <qtsharedmemory.h>
#ifdef Q_OS_UNIX
#include <unistd.h>
#endif
#ifdef Q_OS_WIN32
#include <qt_windows.h>
#endif
static void qt_sleep(int seconds)
{
#ifdef Q_OS_WIN32
Sleep(seconds * 1000);
#else
sleep(seconds);
#endif
}
/*
Constructs a factory with \a nworkers workers, each working in its
own thread. Each worker gets a share of the job of counting to
1000000. Adjusting the number of threads may change the overall
time spent to reach the number 1000000.
All counting is synchronous across threads.
*/
Factory::Factory(int nworkers)
: sharedMemory("Shared memory segment used for counting")
{
int cnt = 1000000;
int share = cnt / nworkers;
for (int i = 0; i < nworkers; ++i) {
if (i == nworkers - 1) share = cnt;
workers.append(new Worker(share));
cnt -= share;
}
}
Factory::~Factory()
{
for (int i=0; i<workers.size(); ++i)
delete workers[i];
}
/*
Creates the shared memory segment and starts the workers. Waits
for all workers to detach from the segment, then destroys it.
*/
void Factory::startCounting()
{
// Create the segment
if (sharedMemory.exists())
sharedMemory.destroy(QtSharedMemory::ForceNoWait);
if (!sharedMemory.create(16)) {
qFatal("Unable to allocate shared memory: %s",
sharedMemory.errorString().toLatin1().constData());
return;
}
// Start all the threads
qDebug("Starting count to 1000000 using %i threads", workers.count());
QList<Worker *>::iterator it;
for (it = workers.begin(); it != workers.end(); ++it)
(*it)->start();
// Loop until an error occurs, or until all threads are done
int lastValue = 0;
bool allDone;
do {
allDone = true;
QList<Worker *>::iterator it;
for (it = workers.begin(); it != workers.end(); ++it) {
if (!(*it)->isFinished()) {
allDone = false;
break;
}
}
if (sharedMemory.lock() && sharedMemory.attach()) {
int value = *(int *)sharedMemory.data();
qDebug("Progress: %7i/%7i | %3i%% | %7i/sec", value, 1000000,
value * 100 / 1000000, (value - lastValue));
lastValue = value;
} else if (sharedMemory.error() != QtSharedMemory::OutOfResources) {
qDebug("The factory was unable to attach to the segment: %s",
sharedMemory.errorString().toLatin1().constData());
allDone = true;
}
sharedMemory.detach();
sharedMemory.unlock();
if (!allDone)
qt_sleep(1);
} while (!allDone);
// Destroy the segment
if (!sharedMemory.destroy()) {
qDebug("Failed to destroy the segment: %s",
sharedMemory.errorString().toLatin1().constData());
}
}
/*
A worker increments the first integer of the shared memory segment
by one, cnt times. It does this in a locked region to avoid race
conditions which are very likely to occur here.
*/
void Worker::run()
{
// Initialize and attach to the shared memory segment
QtSharedMemory mem("Shared memory segment used for counting");
// Loop cnt times, incrementing the first int value in the shared
// memory segment in a locked region.
for (int i = 0; i < cnt; ++i) {
if (!mem.lock()) {
qDebug("A worker failed to lock the segment: %s",
mem.errorString().toLatin1().constData());
break;
}
if (!mem.attach()) {
if (mem.error() == QtSharedMemory::OutOfResources) {
// out of resources
qt_sleep(1);
continue;
}
qDebug("A worker failed to attach to the segment: %s",
mem.errorString().toLatin1().constData());
break;
}
// A sequence of operations that is likely to cause
// unsynchronized access to break.
volatile int *array = (int *) mem.data();
volatile int a = array[0];
++a;
array[0] = a;
mem.detach();
mem.unlock();
}
}
main.cpp:
/****************************************************************************
**
** Copyright (C) 2003-2007 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding a valid Qt Solutions License Agreement may use this
** file in accordance with the rights, responsibilities, and obligations
** contained therein. Please consult your licensing agreement or contact
** [email protected] if any conditions of this licensing are not clear
** to you.
**
** Further information about Qt Solutions licensing is available at:
** http://www.trolltech.com/products/qt/addon/solutions/
** or by contacting [email protected].
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "factory.h"
int main(int argc, char *argv[])
{
int threads = argc > 1 ? QString(argv[1]).toInt() : 0;
if (argc < 2 || threads < 1) {
qDebug("Usage: %s <nthreads>", argv[0]);
qDebug("Counts to 1000000 using nthreads (at least 1) threads");
return 1;
}
if (threads > 7) {
qDebug("*** WARNING: Certain operating systems allow only a limited number");
qDebug(" of shared memory attachments per process. See also");
qDebug(" the QtSharedMemory::attach() documentation.");
}
Factory f(threads);
f.startCounting();
return 0;
};
threadcounter.pro:
TEMPLATE = app
CONFIG -= moc
CONFIG += thread debug console
INCLUDEPATH += .
include(../../src/qtsharedmemory.pri)
# Input
SOURCES += main.cpp factory.cpp
HEADERS += factory.h
| Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies) | Trademarks | Qt Solutions |