| 1 | /****************************************************************************
|
|---|
| 2 | ** $Id: qmutexpool.cpp 2 2005-11-16 15:49:26Z dmik $
|
|---|
| 3 | **
|
|---|
| 4 | ** ...
|
|---|
| 5 | **
|
|---|
| 6 | ** Copyright (C) 2002 Trolltech AS. All rights reserved.
|
|---|
| 7 | **
|
|---|
| 8 | ** This file is part of the tools module of the Qt GUI Toolkit.
|
|---|
| 9 | **
|
|---|
| 10 | ** This file may be distributed under the terms of the Q Public License
|
|---|
| 11 | ** as defined by Trolltech AS of Norway and appearing in the file
|
|---|
| 12 | ** LICENSE.QPL included in the packaging of this file.
|
|---|
| 13 | **
|
|---|
| 14 | ** This file may be distributed and/or modified under the terms of the
|
|---|
| 15 | ** GNU General Public License version 2 as published by the Free Software
|
|---|
| 16 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 17 | ** packaging of this file.
|
|---|
| 18 | **
|
|---|
| 19 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
|---|
| 20 | ** licenses may use this file in accordance with the Qt Commercial License
|
|---|
| 21 | ** Agreement provided with the Software.
|
|---|
| 22 | **
|
|---|
| 23 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|---|
| 24 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|---|
| 25 | **
|
|---|
| 26 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
|---|
| 27 | ** information about Qt Commercial License Agreements.
|
|---|
| 28 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
|---|
| 29 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
|---|
| 30 | **
|
|---|
| 31 | ** Contact info@trolltech.com if any conditions of this licensing are
|
|---|
| 32 | ** not clear to you.
|
|---|
| 33 | **
|
|---|
| 34 | **********************************************************************/
|
|---|
| 35 |
|
|---|
| 36 | #include "qmutexpool_p.h"
|
|---|
| 37 |
|
|---|
| 38 | #ifdef QT_THREAD_SUPPORT
|
|---|
| 39 |
|
|---|
| 40 | #include <qthread.h>
|
|---|
| 41 |
|
|---|
| 42 | Q_EXPORT QMutexPool *qt_global_mutexpool = 0;
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 | /*!
|
|---|
| 46 | \class QMutexPool qmutexpool_p.h
|
|---|
| 47 | \brief The QMutexPool class provides a pool of QMutex objects.
|
|---|
| 48 |
|
|---|
| 49 | \internal
|
|---|
| 50 |
|
|---|
| 51 | \ingroup thread
|
|---|
| 52 |
|
|---|
| 53 | QMutexPool is a convenience class that provides access to a fixed
|
|---|
| 54 | number of QMutex objects.
|
|---|
| 55 |
|
|---|
| 56 | Typical use of a QMutexPool is in situations where it is not
|
|---|
| 57 | possible or feasible to use one QMutex for every protected object.
|
|---|
| 58 | The mutex pool will return a mutex based on the address of the
|
|---|
| 59 | object that needs protection.
|
|---|
| 60 |
|
|---|
| 61 | For example, consider this simple class:
|
|---|
| 62 |
|
|---|
| 63 | \code
|
|---|
| 64 | class Number {
|
|---|
| 65 | public:
|
|---|
| 66 | Number( double n ) : num ( n ) { }
|
|---|
| 67 |
|
|---|
| 68 | void setNumber( double n ) { num = n; }
|
|---|
| 69 | double number() const { return num; }
|
|---|
| 70 |
|
|---|
| 71 | private:
|
|---|
| 72 | double num;
|
|---|
| 73 | };
|
|---|
| 74 | \endcode
|
|---|
| 75 |
|
|---|
| 76 | Adding a QMutex member to the Number class does not make sense,
|
|---|
| 77 | because it is so small. However, in order to ensure that access to
|
|---|
| 78 | each Number is protected, you need to use a mutex. In this case, a
|
|---|
| 79 | QMutexPool would be ideal.
|
|---|
| 80 |
|
|---|
| 81 | Code to calculate the square of a number would then look something
|
|---|
| 82 | like this:
|
|---|
| 83 |
|
|---|
| 84 | \code
|
|---|
| 85 | void calcSquare( Number *num )
|
|---|
| 86 | {
|
|---|
| 87 | QMutexLocker locker( mutexpool.get( num ) );
|
|---|
| 88 | num.setNumber( num.number() * num.number() );
|
|---|
| 89 | }
|
|---|
| 90 | \endcode
|
|---|
| 91 |
|
|---|
| 92 | This function will safely calculate the square of a number, since
|
|---|
| 93 | it uses a mutex from a QMutexPool. The mutex is locked and
|
|---|
| 94 | unlocked automatically by the QMutexLocker class. See the
|
|---|
| 95 | QMutexLocker documentation for more details.
|
|---|
| 96 | */
|
|---|
| 97 |
|
|---|
| 98 | /*!
|
|---|
| 99 | Constructs a QMutexPool, reserving space for \a size QMutexes. If
|
|---|
| 100 | \a recursive is TRUE, all QMutexes in the pool will be recursive
|
|---|
| 101 | mutexes; otherwise they will all be non-recursive (the default).
|
|---|
| 102 |
|
|---|
| 103 | The QMutexes are created when needed, and deleted when the
|
|---|
| 104 | QMutexPool is destructed.
|
|---|
| 105 | */
|
|---|
| 106 | QMutexPool::QMutexPool( bool recursive, int size )
|
|---|
| 107 | : mutex( FALSE ), count( size ), recurs( recursive )
|
|---|
| 108 | {
|
|---|
| 109 | mutexes = new QMutex*[count];
|
|---|
| 110 | for ( int index = 0; index < count; ++index ) {
|
|---|
| 111 | mutexes[index] = 0;
|
|---|
| 112 | }
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | /*!
|
|---|
| 116 | Destructs a QMutexPool. All QMutexes that were created by the pool
|
|---|
| 117 | are deleted.
|
|---|
| 118 | */
|
|---|
| 119 | QMutexPool::~QMutexPool()
|
|---|
| 120 | {
|
|---|
| 121 | QMutexLocker locker( &mutex );
|
|---|
| 122 | for ( int index = 0; index < count; ++index ) {
|
|---|
| 123 | delete mutexes[index];
|
|---|
| 124 | mutexes[index] = 0;
|
|---|
| 125 | }
|
|---|
| 126 | delete [] mutexes;
|
|---|
| 127 | mutexes = 0;
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | /*!
|
|---|
| 131 | Returns a QMutex from the pool. QMutexPool uses the value \a
|
|---|
| 132 | address to determine which mutex is retured from the pool.
|
|---|
| 133 | */
|
|---|
| 134 | QMutex *QMutexPool::get( void *address )
|
|---|
| 135 | {
|
|---|
| 136 | int index = (int) ( (unsigned long) address % count );
|
|---|
| 137 |
|
|---|
| 138 | if ( ! mutexes[index] ) {
|
|---|
| 139 | // mutex not created, create one
|
|---|
| 140 |
|
|---|
| 141 | QMutexLocker locker( &mutex );
|
|---|
| 142 | // we need to check once again that the mutex hasn't been created, since
|
|---|
| 143 | // 2 threads could be trying to create a mutex as the same index...
|
|---|
| 144 | if ( ! mutexes[index] ) {
|
|---|
| 145 | mutexes[index] = new QMutex( recurs );
|
|---|
| 146 | }
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | return mutexes[index];
|
|---|
| 150 | }
|
|---|
| 151 |
|
|---|
| 152 | #endif
|
|---|