source: trunk/src/corelib/tools/qshareddata.cpp@ 986

Last change on this file since 986 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 22.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <qshareddata.h>
43
44QT_BEGIN_NAMESPACE
45
46/*!
47 \class QSharedData
48 \brief The QSharedData class is a base class for shared data objects.
49 \reentrant
50
51 QSharedData is designed to be used with QSharedDataPointer or
52 QExplicitlySharedDataPointer to implement custom \l{implicitly
53 shared} or explicitly shared classes. QSharedData provides
54 \l{thread-safe} reference counting.
55
56 See QSharedDataPointer and QExplicitlySharedDataPointer for details.
57*/
58
59/*! \fn QSharedData::QSharedData()
60 Constructs a QSharedData object with a reference count of 0.
61*/
62
63/*! \fn QSharedData::QSharedData(const QSharedData& other)
64 Constructs a QSharedData object with reference count 0.
65 \a other is ignored.
66*/
67
68/*!
69 \class QSharedDataPointer
70 \brief The QSharedDataPointer class represents a pointer to an implicitly shared object.
71 \since 4.0
72 \reentrant
73
74 QSharedDataPointer\<T\> makes writing your own \l {implicitly
75 shared} classes easy. QSharedDataPointer implements \l {thread-safe}
76 reference counting, ensuring that adding QSharedDataPointers to your
77 \l {reentrant} classes won't make them non-reentrant.
78
79 \l {Implicit sharing} is used by many Qt classes to combine the
80 speed and memory efficiency of pointers with the ease of use of
81 classes. See the \l{Shared Classes} page for more information.
82
83 \target Employee example
84 Suppose you want to make an \c Employee class implicitly shared. The
85 procedure is:
86
87 \list
88
89 \o Define the class \c Employee to have a single data member of
90 type \c {QSharedDataPointer<EmployeeData>}.
91
92 \o Define the \c EmployeeData class derived from \l QSharedData to
93 contain all the data members you would normally have put in the
94 \c Employee class.
95
96 \endlist
97
98 To show this in practice, we review the source code for the
99 implicitly shared \c Employee class. In the header file we define the
100 two classes \c Employee and \c EmployeeData.
101
102 \snippet doc/src/snippets/sharedemployee/employee.h 0
103
104 In class \c Employee, note the single data member, a \e {d pointer}
105 of type \c {QSharedDataPointer<EmployeeData>}. All accesses of
106 employee data must go through the \e {d pointer's} \c
107 {operator->()}. For write accesses, \c {operator->()} will
108 automatically call detach(), which creates a copy of the shared data
109 object if the shared data object's reference count is greater than
110 1. This ensures that writes to one \c Employee object don't affect
111 any other \c Employee objects that share the same \c EmployeeData
112 object.
113
114 Class \c EmployeeData inherits QSharedData, which provides the
115 \e{behind the scenes} reference counter. \c EmployeeData has a default
116 constructor, a copy constructor, and a destructor. Normally, trivial
117 implementations of these are all that is needed in the \e {data}
118 class for an implicitly shared class.
119
120 Implementing the two constructors for class \c Employee is also
121 straightforward. Both create a new instance of \c EmployeeData
122 and assign it to the \e{d pointer} .
123
124 \snippet doc/src/snippets/sharedemployee/employee.h 1
125 \codeline
126 \snippet doc/src/snippets/sharedemployee/employee.h 2
127
128 Note that class \c Employee also has a trivial copy constructor
129 defined, which is not strictly required in this case.
130
131 \snippet doc/src/snippets/sharedemployee/employee.h 7
132
133 The copy constructor is not strictly required here, because class \c
134 EmployeeData is included in the same file as class \c Employee
135 (\c{employee.h}). However, including the private subclass of
136 QSharedData in the same file as the public class containing the
137 QSharedDataPointer is not typical. Normally, the idea is to hide the
138 private subclass of QSharedData from the user by putting it in a
139 separate file which would not be included in the public file. In
140 this case, we would normally put class \c EmployeeData in a separate
141 file, which would \e{not} be included in \c{employee.h}. Instead, we
142 would just predeclare the private subclass \c EmployeeData in \c
143 {employee.h} this way:
144
145 \code
146 class EmployeeData;
147 \endcode
148
149 If we had done it that way here, the copy constructor shown would be
150 required. Since the copy constructor is trivial, you might as well
151 just always include it.
152
153 Behind the scenes, QSharedDataPointer automatically increments the
154 reference count whenever an \c Employee object is copied, assigned,
155 or passed as a parameter. It decrements the reference count whenever
156 an \c Employee object is deleted or goes out of scope. The shared
157 \c EmployeeData object is deleted automatically if and when the
158 reference count reaches 0.
159
160 In a non-const member function of \c Employee, whenever the \e {d
161 pointer} is dereferenced, QSharedDataPointer automatically calls
162 detach() to ensure that the function operates on its own copy of the
163 data.
164
165 \snippet doc/src/snippets/sharedemployee/employee.h 3
166 \codeline
167 \snippet doc/src/snippets/sharedemployee/employee.h 4
168
169 Note that if detach() is called more than once in a member function
170 due to multiple dereferences of the \e {d pointer}, detach() will
171 only create a copy of the shared data the first time it is called,
172 if at all, because on the second and subsequent calls of detach(),
173 the reference count will be 1 again.
174
175 But note that in the second \c Employee constructor, which takes an
176 employee ID and a name, both setId() and setName() are called, but
177 they don't cause \e{copy on write}, because the reference count for
178 the newly constructed \c EmployeeData object has just been set to 1.
179
180 In \c Employee's \e const member functions, dereferencing the \e {d
181 pointer} does \e not cause detach() to be called.
182
183 \snippet doc/src/snippets/sharedemployee/employee.h 5
184 \codeline
185 \snippet doc/src/snippets/sharedemployee/employee.h 6
186
187 Notice that there is no need to implement a copy constructor or an
188 assignment operator for the \c Employee class, because the copy
189 constructor and assignment operator provided by the C++ compiler
190 will do the \e{member by member} shallow copy required. The only
191 member to copy is the \e {d pointer}, which is a QSharedDataPointer,
192 whose \c {operator=()} just increments the reference count of the
193 shared \c EmployeeData object.
194
195 \target Implicit vs Explicit Sharing
196 \section1 Implicit vs Explicit Sharing
197
198 Implicit sharing might not be right for the \c Employee class.
199 Consider a simple example that creates two instances of the
200 implicitly shared \c Employee class.
201
202 \snippet doc/src/snippets/sharedemployee/main.cpp 0
203
204 After the second employee e2 is created and e1 is assigned to it,
205 both \c e1 and \c e2 refer to Albrecht Durer, employee 1001. Both \c
206 Employee objects point to the same instance of \c EmployeeData,
207 which has reference count 2. Then \c {e1.setName("Hans Holbein")} is
208 called to change the employee name, but because the reference count
209 is greater than 1, a \e{copy on write} is performed before the name
210 is changed. Now \c e1 and \c e2 point to different \c EmployeeData
211 objects. They have different names, but both have ID 1001, which is
212 probably not what you want. You can, of course, just continue with
213 \c {e1.setId(1002)}, if you really mean to create a second, unique
214 employee, but if you only want to change the employee's name
215 everywhere, consider using \l {QExplicitlySharedDataPointer}
216 {explicit sharing} in the \c Employee class instead of implicit
217 sharing.
218
219 If you declare the \e {d pointer} in the \c Employee class to be
220 \c {QExplicitlySharedDataPointer<EmployeeData>}, then explicit
221 sharing is used and \e{copy on write} operations are not performed
222 automatically (i.e. detach() is not called in non-const
223 functions). In that case, after \c {e1.setName("Hans Holbein")}, the
224 employee's name has been changed, but both e1 and e2 still refer to
225 the same instance of \c EmployeeData, so there is only one employee
226 with ID 1001.
227
228 In the member function documentation, \e{d pointer} always refers
229 to the internal pointer to the shared data object.
230
231 \sa QSharedData, QExplicitlySharedDataPointer, QScopedPointer, QSharedPointer
232*/
233
234/*! \typedef QSharedDataPointer::Type
235 This is the type of the shared data object. The \e{d pointer}
236 points to an object of this type.
237 */
238
239/*! \typedef QSharedDataPointer::pointer
240 \internal
241 */
242
243/*! \fn T& QSharedDataPointer::operator*()
244 Provides access to the shared data object's members.
245 This function calls detach().
246*/
247
248/*! \fn const T& QSharedDataPointer::operator*() const
249 Provides const access to the shared data object's members.
250 This function does \e not call detach().
251*/
252
253/*! \fn T* QSharedDataPointer::operator->()
254 Provides access to the shared data object's members.
255 This function calls detach().
256*/
257
258/*! \fn const T* QSharedDataPointer::operator->() const
259 Provides const access to the shared data object's members.
260 This function does \e not call detach().
261*/
262
263/*! \fn QSharedDataPointer::operator T*()
264 Returns a pointer to the shared data object.
265 This function calls detach().
266
267 \sa data(), constData()
268*/
269
270/*! \fn QSharedDataPointer::operator const T*() const
271 Returns a pointer to the shared data object.
272 This function does \e not call detach().
273*/
274
275/*! \fn T* QSharedDataPointer::data()
276 Returns a pointer to the shared data object.
277 This function calls detach().
278
279 \sa constData()
280*/
281
282/*! \fn const T* QSharedDataPointer::data() const
283 Returns a pointer to the shared data object.
284 This function does \e not call detach().
285*/
286
287/*! \fn const T* QSharedDataPointer::constData() const
288 Returns a const pointer to the shared data object.
289 This function does \e not call detach().
290
291 \sa data()
292*/
293
294/*! \fn void QSharedDataPointer::swap(QSharedDataPointer &other)
295 Swap this instance's shared data pointer with the shared
296 data pointer in \a other.
297 */
298
299/*! \fn bool QSharedDataPointer::operator==(const QSharedDataPointer<T>& other) const
300 Returns true if \a other and \e this have the same \e{d pointer}.
301 This function does \e not call detach().
302*/
303
304/*! \fn bool QSharedDataPointer::operator!=(const QSharedDataPointer<T>& other) const
305 Returns true if \a other and \e this do \e not have the same
306 \e{d pointer}. This function does \e not call detach().
307*/
308
309/*! \fn QSharedDataPointer::QSharedDataPointer()
310 Constructs a QSharedDataPointer initialized with a null \e{d pointer}.
311*/
312
313/*! \fn QSharedDataPointer::~QSharedDataPointer()
314 Decrements the reference count of the shared data object.
315 If the reference count becomes 0, the shared data object
316 is deleted. \e This is then destroyed.
317*/
318
319/*! \fn QSharedDataPointer::QSharedDataPointer(T* sharedData)
320 Constructs a QSharedDataPointer with \e{d pointer} set to
321 \a sharedData and increments \a{sharedData}'s reference count.
322*/
323
324/*! \fn QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T>& other)
325 Sets the \e{d pointer} of \e this to the \e{d pointer} in
326 \a other and increments the reference count of the shared
327 data object.
328*/
329
330/*! \fn QSharedDataPointer<T>& QSharedDataPointer::operator=(const QSharedDataPointer<T>& other)
331 Sets the \e{d pointer} of \e this to the \e{d pointer} of
332 \a other and increments the reference count of the shared
333 data object. The reference count of the old shared data
334 object of \e this is decremented. If the reference count
335 of the old shared data object becomes 0, the old shared
336 data object is deleted.
337*/
338
339/*! \fn QSharedDataPointer& QSharedDataPointer::operator=(T* sharedData)