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
|
---|