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