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

Last change on this file 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