2006-10-18 13:24:55 -04:00
|
|
|
\section{Reference counting}\label{trefcount}
|
|
|
|
|
2006-10-30 14:26:48 -05:00
|
|
|
\subsection{Why you shouldn't care about it}\label{refcount}
|
2006-10-18 13:24:55 -04:00
|
|
|
|
|
|
|
Many wxWidgets objects use a technique known as \it{reference counting}, also known
|
|
|
|
as {\it copy on write} (COW).
|
|
|
|
This means that when an object is assigned to another, no copying really takes place:
|
|
|
|
only the reference count on the shared object data is incremented and both objects
|
|
|
|
share the same data (a very fast operation).
|
|
|
|
|
|
|
|
But as soon as one of the two (or more) objects is modified, the data has to be
|
|
|
|
copied because the changes to one of the objects shouldn't be seen in the
|
|
|
|
others. As data copying only happens when the object is written to, this is
|
|
|
|
known as COW.
|
|
|
|
|
|
|
|
What is important to understand is that all this happens absolutely
|
|
|
|
transparently to the class users and that whether an object is shared or not
|
|
|
|
is not seen from the outside of the class - in any case, the result of any
|
|
|
|
operation on it is the same.
|
|
|
|
|
2006-10-30 14:26:48 -05:00
|
|
|
\subsection{Object comparison}\label{refcountequality}
|
|
|
|
|
|
|
|
The $==$ and $!=$ operators of \helpref{wxWidgets COW objects}{refcountlist}
|
|
|
|
always do a {\tt deep} comparison.
|
|
|
|
|
|
|
|
This means that the equality operator will return \true if two objects are
|
|
|
|
identic and not only if they share the same data.
|
|
|
|
|
|
|
|
Note that wxWidgets follows the {\it STL philosophy}: when a comparison operator cannot
|
|
|
|
be implemented efficiently (like for e.g. wxImage's $==$ operator which would need to
|
|
|
|
compare pixel-by-pixel the entire image's data), it's not implemented at all.
|
|
|
|
|
|
|
|
That's why not all reference-counted wxWidgets classes provide comparison operators.
|
|
|
|
|
|
|
|
Also note that if you only need to do a {\tt shallow} comparison between two
|
|
|
|
\helpref{wxObject}{wxobject}-derived classes, you should not use the $==$ and $!=$ operators
|
2006-10-30 17:03:53 -05:00
|
|
|
but rather the \helpref{wxObject::IsSameAs}{wxobjectissameas} function.
|
2006-10-30 14:26:48 -05:00
|
|
|
|
|
|
|
|
|
|
|
\subsection{Object destruction}\label{refcountdestruct}
|
|
|
|
|
|
|
|
When a COW object destructor is called, it may not delete the data: if it's shared,
|
|
|
|
the destructor will just decrement the shared data's reference count without destroying it.
|
|
|
|
|
|
|
|
Only when the destructor of the last object owning the data is called, the data is really
|
|
|
|
destroyed. As for all other COW-things, this happens transparently to the class users so
|
|
|
|
that you shouldn't care about it.
|
|
|
|
|
2006-10-18 13:24:55 -04:00
|
|
|
|
2006-10-31 06:39:31 -05:00
|
|
|
\subsection{List of reference-counted wxWidgets classes}\label{refcountlist}
|
|
|
|
|
2006-10-18 13:24:55 -04:00
|
|
|
The following classes in wxWidgets have efficient (i.e. fast) assignment operators
|
|
|
|
and copy constructors since they are reference-counted:
|
|
|
|
|
|
|
|
\helpref{wxAcceleratorTable}{wxacceleratortable}\\
|
2006-10-30 14:26:48 -05:00
|
|
|
\helpref{wxAnimation}{wxanimation}\\
|
|
|
|
\helpref{wxBitmap}{wxbitmap}\\
|
2006-10-18 13:24:55 -04:00
|
|
|
\helpref{wxBrush}{wxbrush}\\
|
|
|
|
\helpref{wxCursor}{wxcursor}\\
|
|
|
|
\helpref{wxFont}{wxfont}\\
|
2006-10-30 14:26:48 -05:00
|
|
|
\helpref{wxIcon}{wxicon}\\
|
2006-10-18 13:24:55 -04:00
|
|
|
\helpref{wxImage}{wximage}\\
|
|
|
|
\helpref{wxMetafile}{wxmetafile}\\
|
|
|
|
\helpref{wxPalette}{wxpalette}\\
|
|
|
|
\helpref{wxPen}{wxpen}\\
|
|
|
|
\helpref{wxRegion}{wxregion}\\
|
2006-12-29 15:22:23 -05:00
|
|
|
\helpref{wxString}{wxstring}\\
|
|
|
|
\helpref{wxVariant}{wxvariant}\\
|
|
|
|
\helpref{wxVariantData}{wxvariantdata}
|
2006-10-18 13:24:55 -04:00
|
|
|
|
2006-10-30 14:26:48 -05:00
|
|
|
Note that the list above reports the objects which are reference-counted in all ports of
|
|
|
|
wxWidgets; some ports may use this tecnique also for other classes.
|
2006-10-18 13:24:55 -04:00
|
|
|
\subsection{Make your own reference-counted class}\label{wxobjectoverview}
|
|
|
|
|
|
|
|
Reference counting can be implemented easily using \helpref{wxObject}{wxobject}
|
|
|
|
and \helpref{wxObjectRefData}{wxobjectrefdata} classes.
|
|
|
|
|
|
|
|
First, derive a new class from \helpref{wxObjectRefData}{wxobjectrefdata} and
|
|
|
|
put there the memory-consuming data.
|
|
|
|
|
|
|
|
Then derive a new class from \helpref{wxObject}{wxobject} and implement there
|
|
|
|
the public interface which will be seen by the user of your class.
|
|
|
|
You'll probably want to add a function to your class which does the cast from
|
|
|
|
\helpref{wxObjectRefData}{wxobjectrefdata} to your class-specific shared data; e.g.:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
MyClassRefData *GetData() const { return wx_static_cast(MyClassRefData*, m_refData); }
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
in fact, all times you'll need to read the data from your wxObject-derived class,
|
|
|
|
you'll need to call such function.
|
|
|
|
|
|
|
|
Very important, all times you need to actually modify the data placed inside your
|
2006-10-28 06:48:11 -04:00
|
|
|
wxObject-derived class, you must first call the wxObject::UnShare
|
2006-10-18 13:24:55 -04:00
|
|
|
function to be sure that the modifications won't affect other instances which are
|
|
|
|
eventually sharing your object's data.
|
|
|
|
|