diff options
Diffstat (limited to 'doc/shclass.doc')
-rw-r--r-- | doc/shclass.doc | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/doc/shclass.doc b/doc/shclass.doc new file mode 100644 index 000000000..c0542f852 --- /dev/null +++ b/doc/shclass.doc @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Qt Shared Classes Documentation +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +/*! +\page shclass.html + +\title Shared Classes + +\keyword reference counting +\keyword implicit sharing +\keyword explicit sharing +\keyword implicitly shared +\keyword explicitly shared +\keyword explicit sharing +\keyword shared implicitly +\keyword shared explicitly + +Many C++ classes in Qt use \e explicit and \e implicit data sharing +to maximize resource usage and minimize copying of data. + +\tableofcontents + +\section1 Overview + +A shared class consists of a pointer to a shared data block that +contains a reference count and the data. + +When a shared object is created, it sets the reference count to 1. The +reference count is incremented whenever a new object references the +shared data, and decremented when the object dereferences the shared +data. The shared data is deleted when the reference count becomes +zero. + +\keyword deep copy +\keyword shallow copy + +When dealing with shared objects, there are two ways of copying an +object. We usually speak about \e deep and \e shallow copies. A deep +copy implies duplicating an object. A shallow copy is a reference +copy, i.e. just a pointer to a shared data block. Making a deep copy +can be expensive in terms of memory and CPU. Making a shallow copy is +very fast, because it only involves setting a pointer and incrementing +the reference count. + +Object assignment (with operator=()) for implicitly and explicitly +shared objects is implemented using shallow copies. A deep copy can be +made by calling a copy() function or by using \l QDeepCopy. + +The benefit of sharing is that a program does not need to duplicate +data unnecessarily, which results in lower memory use and less copying +of data. Objects can easily be assigned, sent as function arguments, +and returned from functions. + +Now comes the distinction between \e explicit and \e implicit sharing. +Explicit sharing means that the programmer must be aware of the fact +that objects share common data. Implicit sharing means that the +sharing mechanism takes place behind the scenes and the programmer +does not need to worry about it. + +\section1 A QByteArray Example + +QByteArray is an example of a shared class that uses explicit sharing. +Example: +\code + //Line a= b= c= + QByteArray a(3),b(2) // 1: {?,?,?} {?,?} + b[0] = 12; b[1] = 34; // 2: {?,?,?} {12,34} + a = b; // 3: {12,34} {12,34} + a[1] = 56; // 4: {12,56} {12,56} + QByteArray c = a; // 5: {12,56} {12,56} {12,56} + a.detach(); // 6: {12,56} {12,56} {12,56} + a[1] = 78; // 7: {12,78} {12,56} {12,56} + b = a.copy(); // 8: {12,78} {12,78} {12,56} + a[1] = 90; // 9: {12,90} {12,78} {12,56} +\endcode + +The assignment \c {a = b} on line 3 throws away \c a's original shared +block (the reference count becomes zero), sets \c a's shared block to +point to \c b's shared block and increments the reference count. + +On line 4, the contents of \c a is modified. \c b is also modified, +because \c a and \c b refer to the same data block. This is the +difference between explicit and implicit sharing (explained below). + +The \c a object detaches from the common data on line 6. Detaching +means that the shared data is copied to make sure that an object has +its own private data. Therefore, modifying \c a on line 7 does not +affect \c b or \c c. + +Finally, on line 8 we make a deep copy of \c a and assign it to \c b, +so that when \c a is modified on line 9, \c b remains unchanged. + + +\section1 Explicit vs. Implicit Sharing + +Implicit sharing automatically detaches the object from a shared block +if the object is about to change and the reference count is greater +than one. (This is often called "copy-on-write".) Explicit sharing +leaves this job to the programmer. If an explicitly shared object is +not detached, changing an object will change all other objects that +refer to the same data. + +Implicit sharing optimizes memory use and copying of data without +this side effect. So why didn't we implement implicit sharing for all +shared classes? The answer is that a class that allows direct access +to its internal data (for efficiency reasons), like QByteArray, cannot +be implicitly shared, because it can be changed without letting +QByteArray know. + +An implicitly shared class has total control of its internal data. In +any member functions that modify its data, it automatically detaches +before modifying the data. + +The QPen class, which uses implicit sharing, detaches from the shared +data in all member functions that change the internal data. + +Code fragment: +\code + void QPen::setStyle( PenStyle s ) + { + detach(); // detach from common data + data->style = s; // set the style member + } + + void QPen::detach() + { + if ( data->count != 1 ) // only if >1 reference + *this = copy(); + } +\endcode + +This is clearly not possible for QByteArray, because the programmer +can do the following: + +\code + QByteArray array( 10 ); + array.fill( 'a' ); + array[0] = 'f'; // will modify array + array.data()[1] = 'i'; // will modify array +\endcode + +If we monitor changes in a QByteArray, the QByteArray class would +become unacceptably slow. + + +\section1 Explicitly Shared Classes + +All classes that are instances of the QMemArray template class are +explicitly shared: + +\list +\i \l QBitArray +\i \l QPointArray +\i \l QByteArray +\i Any other instantiation of \link QMemArray QMemArray\<type\>\endlink +\endlist + +These classes have a detach() function that can be called if you want +your object to get a private copy of the shared data. They also have a +copy() function that returns a deep copy with a reference count of 1. + +The same is true for \l QImage, which does not inherit QMemArray. \l +QMovie is also explicitly shared, but it does not support detach() or +copy(). + +\section1 Implicitly Shared Classes + +The Qt classes that are implicitly shared are: +\list +\i \l QBitmap +\i \l QBrush +\i \l QCursor +\i \l QFont +\i \l QFontInfo +\i \l QFontMetrics +\i \l QIconSet +\i \l QMap +\i \l QPalette +\i \l QPen +\i \l QPicture +\i \l QPixmap +\i \l QRegion +\i \l QRegExp +\i \l QString +\i \l QStringList +\i \l QValueList +\i \l QValueStack +\endlist + +These classes automatically detach from common data if an object is +about to be changed. The programmer will not even notice that the +objects are shared. Thus you should treat separate instances of them +as separate objects. They will always behave as separate objects but +with the added benefit of sharing data whenever possible. For this +reason, you can pass instances of these classes as arguments to +functions by value without concern for the copying overhead. + +Example: +\code + QPixmap p1, p2; + p1.load( "image.bmp" ); + p2 = p1; // p1 and p2 share data + QPainter paint; + paint.begin( &p2 ); // cuts p2 loose from p1 + paint.drawText( 0,50, "Hi" ); + paint.end(); +\endcode + +In this example, \c p1 and \c p2 share data until QPainter::begin() is +called for \c p2, because painting a pixmap will modify it. The same +also happens if anything is \link ::bitBlt() bitBlt()\endlink'ed into +\c p2. + +\warning Do not copy an implicitly shared container (QMap, +QValueVector, etc.) while you are iterating over it. + +\section1 QCString: implicit or explicit? + +\l QCString uses a mixture of implicit and explicit sharing. Functions +inherited from QByteArray, such as data(), employ explicit sharing, while +those only in QCString detach automatically. Thus, QCString is rather an +"experts only" class, provided mainly to ease porting from Qt 1.x to Qt 2.0. +We recommend that you use \l QString, a purely implicitly shared class. + +*/ |