]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: refcount.h | |
3 | // Purpose: topic overview | |
4 | // Author: wxWidgets team | |
5 | // RCS-ID: $Id$ | |
6 | // Licence: wxWindows licence | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | /** | |
10 | ||
11 | @page overview_refcount Reference Counting | |
12 | ||
13 | @li @ref overview_refcount_ignore | |
14 | @li @ref overview_refcount_equality | |
15 | @li @ref overview_refcount_destruct | |
16 | @li @ref overview_refcount_list | |
17 | @li @ref overview_refcount_object | |
18 | ||
19 | ||
20 | <hr> | |
21 | ||
22 | ||
23 | @section overview_refcount_ignore Why You Shouldn't Care About It | |
24 | ||
25 | Many wxWidgets objects use a technique known as <em>reference counting</em>, | |
26 | also known as <em>copy on write</em> (COW). This means that when an object is | |
27 | assigned to another, no copying really takes place. Only the reference count on | |
28 | the shared object data is incremented and both objects share the same data (a | |
29 | very fast operation). | |
30 | ||
31 | But as soon as one of the two (or more) objects is modified, the data has to be | |
32 | copied because the changes to one of the objects shouldn't be seen in the | |
33 | others. As data copying only happens when the object is written to, this is | |
34 | known as COW. | |
35 | ||
36 | What is important to understand is that all this happens absolutely | |
37 | transparently to the class users and that whether an object is shared or not is | |
38 | not seen from the outside of the class - in any case, the result of any | |
39 | operation on it is the same. | |
40 | ||
41 | ||
42 | @section overview_refcount_equality Object Comparison | |
43 | ||
44 | The == and != operators of @ref overview_refcount_list "the reference counted classes" | |
45 | always do a <em>deep comparison</em>. This means that the equality operator | |
46 | will return @true if two objects are identical and not only if they share the | |
47 | same data. | |
48 | ||
49 | Note that wxWidgets follows the <em>STL philosophy</em>: when a comparison | |
50 | operator cannot be implemented efficiently (like for e.g. wxImage's == | |
51 | operator which would need to compare the entire image's data, pixel-by-pixel), | |
52 | it's not implemented at all. That's why not all reference counted classes | |
53 | provide comparison operators. | |
54 | ||
55 | Also note that if you only need to do a @c shallow comparison between two | |
56 | wxObject derived classes, you should not use the == and != operators but | |
57 | rather the wxObject::IsSameAs() function. | |
58 | ||
59 | ||
60 | @section overview_refcount_destruct Object Destruction | |
61 | ||
62 | When a COW object destructor is called, it may not delete the data: if it's | |
63 | shared, the destructor will just decrement the shared data's reference count | |
64 | without destroying it. Only when the destructor of the last object owning the | |
65 | data is called, the data is really destroyed. Just like all other COW-things, | |
66 | this happens transparently to the class users so that you shouldn't care about | |
67 | it. | |
68 | ||
69 | ||
70 | @section overview_refcount_list List of Reference Counted Classes | |
71 | ||
72 | The following classes in wxWidgets have efficient (i.e. fast) assignment | |
73 | operators and copy constructors since they are reference-counted: | |
74 | ||
75 | @li wxAcceleratorTable | |
76 | @li wxAnimation | |
77 | @li wxBitmap | |
78 | @li wxBrush | |
79 | @li wxCursor | |
80 | @li wxFont | |
81 | @li wxGraphicsBrush | |
82 | @li wxGraphicsContext | |
83 | @li wxGraphicsFont | |
84 | @li wxGraphicsMatrix | |
85 | @li wxGraphicsPath | |
86 | @li wxGraphicsPen | |
87 | @li wxIcon | |
88 | @li wxImage | |
89 | @li wxMetafile | |
90 | @li wxPalette | |
91 | @li wxPen | |
92 | @li wxRegion | |
93 | @li wxString | |
94 | @li wxVariant | |
95 | @li wxVariantData | |
96 | ||
97 | Note that the list above reports the objects which are reference counted in all | |
98 | ports of wxWidgets; some ports may use this technique also for other classes. | |
99 | ||
100 | All the objects implement a function @b IsOk() to test if they are referencing valid | |
101 | data; when the objects are in uninitialized state, you can only use the @b IsOk() getter; | |
102 | trying to call any other getter, e.g. wxBrush::GetStyle() on the ::wxNullBrush object, | |
103 | will result in an assert failure in debug builds. | |
104 | ||
105 | ||
106 | @section overview_refcount_object Making Your Own Reference Counted Class | |
107 | ||
108 | Reference counting can be implemented easily using wxObject or using | |
109 | the intermediate wxRefCounter class directly. | |
110 | Alternatively, you can also use the wxObjectDataPtr<T> template. | |
111 | ||
112 | First, derive a new class from wxRefCounter (or wxObjectRefData when | |
113 | using a wxObject derived class) and put the memory-consuming data in it. | |
114 | ||
115 | Then derive a new class from wxObject and implement there the public interface | |
116 | which will be seen by the user of your class. You'll probably want to add a | |
117 | function to your class which does the cast from wxObjectRefData to your | |
118 | class-specific shared data. For example: | |
119 | ||
120 | @code | |
121 | MyClassRefData* GetData() const | |
122 | { | |
123 | return wx_static_cast(MyClassRefData*, m_refData); | |
124 | } | |
125 | @endcode | |
126 | ||
127 | In fact, any time you need to read the data from your wxObject-derived class, | |
128 | you will need to call this function. | |
129 | ||
130 | @note Any time you need to actually modify the data placed inside your wxObject | |
131 | derived class, you must first call the wxObject::UnShare() function to ensure | |
132 | that the modifications won't affect other instances which are eventually | |
133 | sharing your object's data. | |
134 | ||
135 | */ | |
136 |