|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** TQt Shared Classes Documentation
|
|
|
|
**
|
|
|
|
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
|
|
|
**
|
|
|
|
** This file is part of the TQt 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 TQt Foundation.
|
|
|
|
**
|
|
|
|
** Please review the following information to ensure GNU General
|
|
|
|
** Public Licensing requirements 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 TQt 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 TQImage, which does not inherit QMemArray. \l
|
|
|
|
QMovie is also explicitly shared, but it does not support detach() or
|
|
|
|
copy().
|
|
|
|
|
|
|
|
\section1 Implicitly Shared Classes
|
|
|
|
|
|
|
|
The TQt 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 TQIconSet
|
|
|
|
\i \l TQMap
|
|
|
|
\i \l QPalette
|
|
|
|
\i \l QPen
|
|
|
|
\i \l QPicture
|
|
|
|
\i \l QPixmap
|
|
|
|
\i \l QRegion
|
|
|
|
\i \l QRegExp
|
|
|
|
\i \l TQString
|
|
|
|
\i \l TQStringList
|
|
|
|
\i \l TQValueList
|
|
|
|
\i \l TQValueStack
|
|
|
|
\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 (TQMap,
|
|
|
|
TQValueVector, 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 TQt 1.x to TQt 2.0.
|
|
|
|
We recommend that you use \l TQString, a purely implicitly shared class.
|
|
|
|
|
|
|
|
*/
|