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 |