]>
Commit | Line | Data |
---|---|---|
40131743 RR |
1 | \section{Reference counting}\label{trefcount} |
2 | ||
55ccdb93 | 3 | \subsection{Why you shouldn't care about it}\label{refcount} |
40131743 RR |
4 | |
5 | Many wxWidgets objects use a technique known as \it{reference counting}, also known | |
6 | as {\it copy on write} (COW). | |
7 | This means that when an object is assigned to another, no copying really takes place: | |
8 | only the reference count on the shared object data is incremented and both objects | |
9 | share the same data (a very fast operation). | |
10 | ||
11 | But as soon as one of the two (or more) objects is modified, the data has to be | |
12 | copied because the changes to one of the objects shouldn't be seen in the | |
13 | others. As data copying only happens when the object is written to, this is | |
14 | known as COW. | |
15 | ||
16 | What is important to understand is that all this happens absolutely | |
17 | transparently to the class users and that whether an object is shared or not | |
18 | is not seen from the outside of the class - in any case, the result of any | |
19 | operation on it is the same. | |
20 | ||
55ccdb93 VZ |
21 | \subsection{Object comparison}\label{refcountequality} |
22 | ||
23 | The $==$ and $!=$ operators of \helpref{wxWidgets COW objects}{refcountlist} | |
24 | always do a {\tt deep} comparison. | |
25 | ||
26 | This means that the equality operator will return \true if two objects are | |
27 | identic and not only if they share the same data. | |
28 | ||
29 | Note that wxWidgets follows the {\it STL philosophy}: when a comparison operator cannot | |
30 | be implemented efficiently (like for e.g. wxImage's $==$ operator which would need to | |
31 | compare pixel-by-pixel the entire image's data), it's not implemented at all. | |
32 | ||
33 | That's why not all reference-counted wxWidgets classes provide comparison operators. | |
34 | ||
35 | Also note that if you only need to do a {\tt shallow} comparison between two | |
36 | \helpref{wxObject}{wxobject}-derived classes, you should not use the $==$ and $!=$ operators | |
a3ab1c18 | 37 | but rather the \helpref{wxObject::IsSameAs}{wxobjectissameas} function. |
55ccdb93 VZ |
38 | |
39 | ||
40 | \subsection{Object destruction}\label{refcountdestruct} | |
41 | ||
42 | When a COW object destructor is called, it may not delete the data: if it's shared, | |
43 | the destructor will just decrement the shared data's reference count without destroying it. | |
44 | ||
45 | Only when the destructor of the last object owning the data is called, the data is really | |
46 | destroyed. As for all other COW-things, this happens transparently to the class users so | |
47 | that you shouldn't care about it. | |
48 | ||
40131743 | 49 | |
0df2f30c VZ |
50 | \subsection{List of reference-counted wxWidgets classes}\label{refcountlist} |
51 | ||
40131743 RR |
52 | The following classes in wxWidgets have efficient (i.e. fast) assignment operators |
53 | and copy constructors since they are reference-counted: | |
54 | ||
55 | \helpref{wxAcceleratorTable}{wxacceleratortable}\\ | |
55ccdb93 VZ |
56 | \helpref{wxAnimation}{wxanimation}\\ |
57 | \helpref{wxBitmap}{wxbitmap}\\ | |
40131743 RR |
58 | \helpref{wxBrush}{wxbrush}\\ |
59 | \helpref{wxCursor}{wxcursor}\\ | |
60 | \helpref{wxFont}{wxfont}\\ | |
55ccdb93 | 61 | \helpref{wxIcon}{wxicon}\\ |
40131743 RR |
62 | \helpref{wxImage}{wximage}\\ |
63 | \helpref{wxMetafile}{wxmetafile}\\ | |
64 | \helpref{wxPalette}{wxpalette}\\ | |
65 | \helpref{wxPen}{wxpen}\\ | |
66 | \helpref{wxRegion}{wxregion}\\ | |
631787c4 VZ |
67 | \helpref{wxString}{wxstring}\\ |
68 | \helpref{wxVariant}{wxvariant}\\ | |
69 | \helpref{wxVariantData}{wxvariantdata} | |
40131743 | 70 | |
55ccdb93 VZ |
71 | Note that the list above reports the objects which are reference-counted in all ports of |
72 | wxWidgets; some ports may use this tecnique also for other classes. | |
40131743 RR |
73 | \subsection{Make your own reference-counted class}\label{wxobjectoverview} |
74 | ||
75 | Reference counting can be implemented easily using \helpref{wxObject}{wxobject} | |
76 | and \helpref{wxObjectRefData}{wxobjectrefdata} classes. | |
77 | ||
78 | First, derive a new class from \helpref{wxObjectRefData}{wxobjectrefdata} and | |
79 | put there the memory-consuming data. | |
80 | ||
81 | Then derive a new class from \helpref{wxObject}{wxobject} and implement there | |
82 | the public interface which will be seen by the user of your class. | |
83 | You'll probably want to add a function to your class which does the cast from | |
84 | \helpref{wxObjectRefData}{wxobjectrefdata} to your class-specific shared data; e.g.: | |
85 | ||
86 | \begin{verbatim} | |
87 | MyClassRefData *GetData() const { return wx_static_cast(MyClassRefData*, m_refData); } | |
88 | \end{verbatim} | |
89 | ||
90 | in fact, all times you'll need to read the data from your wxObject-derived class, | |
91 | you'll need to call such function. | |
92 | ||
93 | Very important, all times you need to actually modify the data placed inside your | |
d479632a | 94 | wxObject-derived class, you must first call the wxObject::UnShare |
40131743 RR |
95 | function to be sure that the modifications won't affect other instances which are |
96 | eventually sharing your object's data. | |
97 |