1 | 144c144
|
---|
2 | < a size overhead for each allocation to store bookeeping information and a
|
---|
3 | ---
|
---|
4 | > a size overhead for each allocation to store bookkeeping information and a
|
---|
5 | 163c163
|
---|
6 | < In some situation intrusives containers offer a no-throw guarantee that can't be
|
---|
7 | ---
|
---|
8 | > In some situations intrusive containers offer a no-throw guarantee that can't be
|
---|
9 | 171c171
|
---|
10 | < memory managed is done with intrusive containers. Memory management usually is not a predicable
|
---|
11 | ---
|
---|
12 | > memory management is done with intrusive containers. Memory management usually is not a predicable
|
---|
13 | 178c178
|
---|
14 | < maintenance information needed by the container. Hence, whenever a certain type shall
|
---|
15 | ---
|
---|
16 | > maintenance information needed by the container. Hence, whenever a certain type will
|
---|
17 | 183c183
|
---|
18 | < * In intrusive containers you don't store a copy of an object, [*but they rather the original object
|
---|
19 | ---
|
---|
20 | > * In intrusive containers you don't store a copy of an object, [*but rather the original object
|
---|
21 | 197,198c197,198
|
---|
22 | < containers don't have allocation capabilities, these operations have no sense. However,
|
---|
23 | < swapping can be used to implement move-capabilities. To ease the implementation of
|
---|
24 | ---
|
---|
25 | > containers don't have allocation capabilities, these operations make no sense. However,
|
---|
26 | > swapping can be used to implement move capabilities. To ease the implementation of
|
---|
27 | 203,204c203,204
|
---|
28 | < * Analyzing thread-safety of a program that uses containers is harder with intrusive containers, becuase
|
---|
29 | < the container might be modified indirectly without an explicitly call to a container member.
|
---|
30 | ---
|
---|
31 | > * Analyzing the thread safety of a program that uses containers is harder with intrusive containers, because
|
---|
32 | > the container might be modified indirectly without an explicit call to a container member.
|
---|
33 | 236,237c236,237
|
---|
34 | < container. We will take a simple intrusive container, like an intrusive list
|
---|
35 | < ([classref boost::intrusive::list boost::intrusive::list]) for the following
|
---|
36 | ---
|
---|
37 | > container. We will take a simple intrusive container, the intrusive list
|
---|
38 | > ([classref boost::intrusive::list boost::intrusive::list]), for the following
|
---|
39 | 315c315
|
---|
40 | < Some options configured for the hook (the type of the pointers, link mode...)
|
---|
41 | ---
|
---|
42 | > Some options configured for the hook (the type of the pointers, link mode, etc.)
|
---|
43 | 329c329
|
---|
44 | < (for example, STL-like containers, use the `size_type` defined by their allocator).
|
---|
45 | ---
|
---|
46 | > (for example, STL-like containers use the `size_type` defined by their allocator).
|
---|
47 | 431,432c431,432
|
---|
48 | < You can insert the same object in several intrusive containers at the same time, just
|
---|
49 | < using one hook for each container. This is a full example using base and member hooks:
|
---|
50 | ---
|
---|
51 | > You can insert the same object in several intrusive containers at the same time,
|
---|
52 | > using one hook per container. This is a full example using base and member hooks:
|
---|
53 | 459c459
|
---|
54 | < issue and...
|
---|
55 | ---
|
---|
56 | > issue and:
|
---|
57 | 470c470
|
---|
58 | < you have a vector of objects (say, `std::vector<Object>`) and you also have a list
|
---|
59 | ---
|
---|
60 | > you have a vector of objects (say, `std::vector<Object>`), and you also have a list
|
---|
61 | 472c472
|
---|
62 | < from the list iterator (`std::list<Object*>::iterator`) needs two steps:
|
---|
63 | ---
|
---|
64 | > from the list iterator (`std::list<Object*>::iterator`) requires two steps:
|
---|
65 | 478,481c478,481
|
---|
66 | < (vector's memory is guaranteed to be contiguous), and form something
|
---|
67 | < like a data block, list nodes can stay dispersed in the heap memory.
|
---|
68 | < Hence depending on your system you can get a lot of cache misses. The same doesn't hold
|
---|
69 | < for an intrusive list. Indeed, dereferencing an an iterator from an intrusive list is performed in
|
---|
70 | ---
|
---|
71 | > (a vector's memory is guaranteed to be contiguous), and form something
|
---|
72 | > like a data block, list nodes may be dispersed in the heap memory.
|
---|
73 | > Hence depending on your system you might get a lot of cache misses. The same doesn't hold
|
---|
74 | > for an intrusive list. Indeed, dereferencing an iterator from an intrusive list is performed in
|
---|
75 | 487c487
|
---|
76 | < in the same container as shown in the following example:
|
---|
77 | ---
|
---|
78 | > in the same container, as shown in the following example:
|
---|
79 | 496c496
|
---|
80 | < posible or desirable.
|
---|
81 | ---
|
---|
82 | > possible or desirable.
|
---|
83 | 507,508c507,508
|
---|
84 | < basic operations that can be applied to a groups of nodes. It's independent
|
---|
85 | < from the node definition, and it's configured taking a NodeTraits template
|
---|
86 | ---
|
---|
87 | > basic operations that can be applied to a group of nodes. It's independent
|
---|
88 | > from the node definition and configured using a NodeTraits template
|
---|
89 | 510c510
|
---|
90 | < [[Node Traits][A class that stores basic information and operations to insert a node in a group of nodes.]]
|
---|
91 | ---
|
---|
92 | > [[Node Traits][A class that stores basic information and operations to insert a node into a group of nodes.]]
|
---|
93 | 531c531
|
---|
94 | < * [*set/multiset/rbtree]: A `std::set/std::multiset` like intrusive associative containers
|
---|
95 | ---
|
---|
96 | > * [*set/multiset/rbtree]: `std::set/std::multiset` like intrusive associative containers
|
---|
97 | 541c541
|
---|
98 | < * [*splay_set/splay_multiset/splaytree]: A `std::set/std::multiset` like intrusive associative
|
---|
99 | ---
|
---|
100 | > * [*splay_set/splay_multiset/splaytree]: `std::set/std::multiset` like intrusive associative
|
---|
101 | 549c549
|
---|
102 | < balance factor to achieve the desised rebalancing frequency/search time compromise.
|
---|
103 | ---
|
---|
104 | > balance factor to achieve the desired rebalancing frequency/search time compromise.
|
---|
105 | 555c555
|
---|
106 | < * [*unordered_set/unordered_multiset]: A `std::tr1::unordered_set/std::tr1::unordered_multiset`
|
---|
107 | ---
|
---|
108 | > * [*unordered_set/unordered_multiset]: `std::tr1::unordered_set/std::tr1::unordered_multiset`
|
---|
109 | 558c558
|
---|
110 | < Many operations have an amortized constant time complexity.
|
---|
111 | ---
|
---|
112 | > Many operations have amortized constant time complexity.
|
---|
113 | 563,564c563,564
|
---|
114 | < * [*Linear time size]: The intrusive container doesn't hold a size member that it's
|
---|
115 | < updated with every insertion/erasure. This implies that the `size()` function has not constant
|
---|
116 | ---
|
---|
117 | > * [*Linear time size]: The intrusive container doesn't hold a size member that is
|
---|
118 | > updated with every insertion/erasure. This implies that the `size()` function doesn't have constant
|
---|
119 | 566c566
|
---|
120 | < `splice()` taking a range of iterators in linked lists have constant time complexity
|
---|
121 | ---
|
---|
122 | > `splice()` taking a range of iterators in linked lists, have constant time complexity
|
---|
123 | 569c569
|
---|
124 | < * [*Constant time size]: The intrusive container holds a size member that it's updated
|
---|
125 | ---
|
---|
126 | > * [*Constant time size]: The intrusive container holds a size member that is updated
|
---|
127 | 588c588
|
---|
128 | < and can convert some constant time operations in linear time operations.
|
---|
129 | ---
|
---|
130 | > and can convert some constant time operations to linear time operations.
|
---|
131 | 592c592
|
---|
132 | < having any reference to the container.
|
---|
133 | ---
|
---|
134 | > referring to the container.
|
---|
135 | 596c596
|
---|
136 | < be configured to use any type of pointers. This configuration information is also
|
---|
137 | ---
|
---|
138 | > be configured to use any type of pointer. This configuration information is also
|
---|
139 | 614c614
|
---|
140 | < //Configuring explicity the safe mode
|
---|
141 | ---
|
---|
142 | > //Configuring the safe mode explicitly
|
---|
143 | 618,619c618,619
|
---|
144 | < Thanks to the safe-mode the user can detect without any external reference, if the object
|
---|
145 | < is actually inserted in a container. Let's review the basic features of the safe-mode:
|
---|
146 | ---
|
---|
147 | > With the safe mode the user can detect if the object
|
---|
148 | > is actually inserted in a container without any external reference. Let's review the basic features of the safe mode:
|
---|
149 | 621c621
|
---|
150 | < * Hooks' constructor puts the hook in a well-known default state.
|
---|
151 | ---
|
---|
152 | > * Hook's constructor puts the hook in a well-known default state.
|
---|
153 | 623c623
|
---|
154 | < * Hooks' destructor checks if the hook is in the well-known default state. If not,
|
---|
155 | ---
|
---|
156 | > * Hook's destructor checks if the hook is in the well-known default state. If not,
|
---|
157 | 626c626
|
---|
158 | < * Every time an object is being inserted in the intrusive container, the container
|
---|
159 | ---
|
---|
160 | > * Every time an object is inserted in the intrusive container, the container
|
---|
161 | 634c634
|
---|
162 | < has been inserted in a container calling the `is_linked()` member function.
|
---|
163 | ---
|
---|
164 | > has been inserted in a container by calling the `is_linked()` member function.
|
---|
165 | 636c636
|
---|
166 | < in a container, the hook is in the default state and if it's inserted in a container, the
|
---|
167 | ---
|
---|
168 | > in a container, the hook is in the default state, and if it is inserted in a container, the
|
---|
169 | 658c658
|
---|
170 | < If any of these macros is not redefined, the assertion will be defaul to `BOOST_ASSERT`.
|
---|
171 | ---
|
---|
172 | > If any of these macros is not redefined, the assertion will default to `BOOST_ASSERT`.
|
---|
173 | 673,674c673,674
|
---|
174 | < node from the container at any moment, without having any reference to the container,
|
---|
175 | < if the user want to do so.
|
---|
176 | ---
|
---|
177 | > node from the container at any time, without having any reference to the container,
|
---|
178 | > if the user wants to do so.
|
---|
179 | 676c676
|
---|
180 | < These hooks have exactly the same size overhead as their analogue non auto-unlinking
|
---|
181 | ---
|
---|
182 | > These hooks have exactly the same size overhead as their analog non auto-unlinking
|
---|
183 | 683c683
|
---|
184 | < without using any reference to the container.
|
---|
185 | ---
|
---|
186 | > without referring to the container.
|
---|
187 | 699,700c699,700
|
---|
188 | < * Every time an object is being inserted in the intrusive container, the container
|
---|
189 | < checks if the hook is the well-known default state. If not,
|
---|
190 | ---
|
---|
191 | > * Every time an object is inserted in the intrusive container, the container
|
---|
192 | > checks if the hook is in the well-known default state. If not,
|
---|
193 | 703c703
|
---|
194 | < * Every time an object is being erased from the intrusive container, the container
|
---|
195 | ---
|
---|
196 | > * Every time an object is erased from an intrusive container, the container
|
---|
197 | 766,768c766,768
|
---|
198 | < that imposes is 1 pointer per node. The size of an empty, non constant-time size
|
---|
199 | < [classref boost::intrusive::slist slist], is the size of 1 pointer. This
|
---|
200 | < lightweight memory overhead comes with its drawbacks, though: many operations have
|
---|
201 | ---
|
---|
202 | > it imposes is 1 pointer per node. The size of an empty, non constant-time size
|
---|
203 | > [classref boost::intrusive::slist slist] is the size of 1 pointer. This
|
---|
204 | > lightweight memory overhead comes with drawbacks, though: many operations have
|
---|
205 | 776c776
|
---|
206 | < constructing more elaborated containers, singly linked lists are essential
|
---|
207 | ---
|
---|
208 | > constructing more elaborate containers, singly linked lists are essential
|
---|
209 | 834,835c834,835
|
---|
210 | < to configure the container (to know about value traits go to the section
|
---|
211 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
212 | ---
|
---|
213 | > to configure the container. (To learn about value traits go to the section
|
---|
214 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
215 | 875,876c875,876
|
---|
216 | < that imposes is 2 pointers per node. An empty, non constant-time size [classref boost::intrusive::list list]
|
---|
217 | < has also the size of 2 pointers. [classref boost::intrusive::list list]
|
---|
218 | ---
|
---|
219 | > it imposes is 2 pointers per node. An empty, non constant-time size [classref boost::intrusive::list list]
|
---|
220 | > also has the size of 2 pointers. [classref boost::intrusive::list list]
|
---|
221 | 878c878
|
---|
222 | < and provides bidirectional iterator. It's recommendable to use use
|
---|
223 | ---
|
---|
224 | > and provides a bidirectional iterator. It is recommended to use
|
---|
225 | 936,937c936,937
|
---|
226 | < to configure the container (to know about value traits go to the section
|
---|
227 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
228 | ---
|
---|
229 | > to configure the container. (To learn about value traits go to the section
|
---|
230 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
231 | 977c977
|
---|
232 | < searches, insertions, erasures, etc... [classref boost::intrusive::set set] and
|
---|
233 | ---
|
---|
234 | > searches, insertions, erasures, etc. [classref boost::intrusive::set set] and
|
---|
235 | 1059,1060c1059,1060
|
---|
236 | < to configure the container (to know about value traits go to the section
|
---|
237 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
238 | ---
|
---|
239 | > to configure the container. (To learn about value traits go to the section
|
---|
240 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
241 | 1244,1245c1244,1245
|
---|
242 | < to configure the container (to know about value traits go to the section
|
---|
243 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
244 | ---
|
---|
245 | > to configure the container. (To learn about value traits go to the section
|
---|
246 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
247 | 1327c1327
|
---|
248 | < Splay trees are self-adjusting binary search trees used tipically in caches, memory
|
---|
249 | ---
|
---|
250 | > Splay trees are self-adjusting binary search trees used typically in caches, memory
|
---|
251 | 1329c1329
|
---|
252 | < accessed elements have better access times that elements accessed less frequently.
|
---|
253 | ---
|
---|
254 | > accessed elements have better access times than elements accessed less frequently.
|
---|
255 | 1341c1341
|
---|
256 | < An empty, non constant-time size splay container has also the size of 3 pointers.
|
---|
257 | ---
|
---|
258 | > An empty, non constant-time size splay container has also a size of 3 pointers.
|
---|
259 | 1346c1346
|
---|
260 | < operations like searches, insertions, erasures, etc... but if some elements are
|
---|
261 | ---
|
---|
262 | > operations like searches, insertions, erasures, etc., but if some elements are
|
---|
263 | 1353c1353
|
---|
264 | < `count()`...
|
---|
265 | ---
|
---|
266 | > `count()`, etc.
|
---|
267 | 1426,1427c1426,1427
|
---|
268 | < to configure the container (to know about value traits go to the section
|
---|
269 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
270 | ---
|
---|
271 | > to configure the container. (To learn about value traits go to the section
|
---|
272 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
273 | 1451c1451
|
---|
274 | < [classref boost::intrusive::sg_multiset sg_multiset] so a programmer
|
---|
275 | ---
|
---|
276 | > [classref boost::intrusive::sg_multiset sg_multiset]. A programmer
|
---|
277 | 1453,1454c1453,1454
|
---|
278 | < can be introduced in some situations in an splay container but that
|
---|
279 | < can also be introduced in other compatible containers as well when
|
---|
280 | ---
|
---|
281 | > can be inserted in some situations in an splay container but
|
---|
282 | > also inserted in other compatible containers when
|
---|
283 | 1482c1482
|
---|
284 | < and because red-black trees also take O(log n) time for the basic operations.
|
---|
285 | ---
|
---|
286 | > and because both take O(log n) time for basic operations.
|
---|
287 | 1503c1503
|
---|
288 | < has also the size of 3 pointers and an integer (3 pointers when optimized for size).
|
---|
289 | ---
|
---|
290 | > also has a size of 3 pointers and an integer (3 pointers when optimized for size).
|
---|
291 | 1574,1575c1574,1575
|
---|
292 | < to configure the container (to know about value traits go to the section
|
---|
293 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
294 | ---
|
---|
295 | > to configure the container. (To learn about value traits go to the section
|
---|
296 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
297 | 1725,1726c1725,1726
|
---|
298 | < to configure the container (to know about value traits go to the section
|
---|
299 | < titled [link intrusive.value_traits Containers with custom ValueTraits].
|
---|
300 | ---
|
---|
301 | > to configure the container. (To learn about value traits go to the section
|
---|
302 | > [link intrusive.value_traits Containers with custom ValueTraits].)
|
---|
303 | 1789c1789
|
---|
304 | < like `equal_range`, `lower_bound`, `upper_bound`...
|
---|
305 | ---
|
---|
306 | > like `equal_range`, `lower_bound`, `upper_bound`, etc.
|
---|
307 | 1791c1791
|
---|
308 | < However, sometimes the object to be searched it's quite expensive to construct:
|
---|
309 | ---
|
---|
310 | > However, sometimes the object to be searched is quite expensive to construct:
|
---|
311 | 1808c1808
|
---|
312 | < [*have enough information to find the object]. In this case, a name it's enough
|
---|
313 | ---
|
---|
314 | > [*have enough information to find the object]. In this case, a name is enough
|
---|
315 | 1865c1865
|
---|
316 | < * if the insertion is possible (there is no equivalent value) collects all the needed information
|
---|
317 | ---
|
---|
318 | > * if the insertion is possible (there is no equivalent value) `insert_check` collects all the needed information
|
---|
319 | 1874c1874
|
---|
320 | < `insert_check` and `insert_commit` will come handy
|
---|
321 | ---
|
---|
322 | > `insert_check` and `insert_commit` will come in handy
|
---|
323 | 1920c1920
|
---|
324 | < will call "disposer" function object for every removed element. [classref boost::intrusive::list list] offers
|
---|
325 | ---
|
---|
326 | > will call the "disposer" function object for every removed element. [classref boost::intrusive::list list] offers
|
---|
327 | 1922c1922
|
---|
328 | < `remove_and_dispose`...
|
---|
329 | ---
|
---|
330 | > `remove_and_dispose`, etc.
|
---|
331 | 1949c1949
|
---|
332 | < Apart from the container to be cloned, `clone_from` takes two function objects as arguments. For example, the
|
---|
333 | ---
|
---|
334 | > Apart from the container to be cloned, `clone_from` takes two function objects as arguments. For example, consider the
|
---|
335 | 1968,1969c1968,1969
|
---|
336 | < * First clears and disposes all the elements from *this using the disposer function object.
|
---|
337 | < * After that starts cloning all the elements of the source container using the cloner function object.
|
---|
338 | ---
|
---|
339 | > * First it clears and disposes all the elements from *this using the disposer function object.
|
---|
340 | > * After that it starts cloning all the elements of the source container using the cloner function object.
|
---|
341 | 2001c2001
|
---|
342 | < Not every smart pointer is compatible with [*Boost.Intrusive], the smart pointer must
|
---|
343 | ---
|
---|
344 | > Not every smart pointer is compatible with [*Boost.Intrusive]; the smart pointer must
|
---|
345 | 2011c2011
|
---|
346 | < ADL. For example, for `boost::interprocess::offset_ptr` `detail::get_pointer` is defined
|
---|
347 | ---
|
---|
348 | > ADL. For example, for `boost::interprocess::offset_ptr`, `detail::get_pointer` is defined
|
---|
349 | 2059,2060c2059,2060
|
---|
350 | < explained in the [link intrusive.value_traits.stateful_value_traits Stateful value traits] section,
|
---|
351 | < but the programmer uses hooks provided by [*Boost.Intrusive], those functions
|
---|
352 | ---
|
---|
353 | > explained in the [link intrusive.value_traits.stateful_value_traits Stateful value traits] section;
|
---|
354 | > if the programmer uses hooks provided by [*Boost.Intrusive], those functions
|
---|
355 | 2078c2078
|
---|
356 | < unlink a node from another group of nodes... For example, a circular
|
---|
357 | ---
|
---|
358 | > unlink a node from another group of nodes, etc. For example, a circular
|
---|
359 | 2082c2082
|
---|
360 | < the needed interface. As an example, here is a class that implements algorithms
|
---|
361 | ---
|
---|
362 | > the needed interface. As an example, here is a class that implements operations7'
|
---|
363 | 2119,2123c2119,2123
|
---|
364 | < operations on a node that forms a group of nodes:
|
---|
365 | < the type of the node, a function to obtain the pointer to the next node...
|
---|
366 | < [*Node Traits] are the configuration information [*Node Algorithms]
|
---|
367 | < need. Each type of [*Node Algorithms] expects an interface that compatible
|
---|
368 | < [*Node Traits] must implement.
|
---|
369 | ---
|
---|
370 | > operations on a node within a group of nodes:
|
---|
371 | > the type of the node, a function to obtain the pointer to the next node, etc.
|
---|
372 | > [*Node Traits] specify the configuration information [*Node Algorithms]
|
---|
373 | > need. Each type of [*Node Algorithm] expects an interface that compatible
|
---|
374 | > [*Node Traits] classes must implement.
|
---|
375 | 2152c2152
|
---|
376 | < contains a node object, that will be used to form the group of nodes:
|
---|
377 | ---
|
---|
378 | > contains a node object that will be used to form the group of nodes:
|
---|
379 | 2192c2192
|
---|
380 | < value types that use different hooks. An intrusive container is also more elaborated
|
---|
381 | ---
|
---|
382 | > value types that use different hooks. An intrusive container is also more elaborate
|
---|
383 | 2194c2194
|
---|
384 | < size information, it can offer debugging facilities...
|
---|
385 | ---
|
---|
386 | > size information, it can offer debugging facilities, etc.
|
---|
387 | 2386c2386
|
---|
388 | < the pointers to the left and right nodes to itself and whose color is red.
|
---|
389 | ---
|
---|
390 | > the left and right node pointers point to itself, and whose color is red.
|
---|
391 | 2457c2457
|
---|
392 | < the pointers to the left and right nodes to itself.
|
---|
393 | ---
|
---|
394 | > and whose left and right nodes pointers point to itself.
|
---|
395 | 2641c2641
|
---|
396 | < `ValueTraits` also store information about the link policy of the values to be inserted.
|
---|
397 | ---
|
---|
398 | > `ValueTraits` also stores information about the link policy of the values to be inserted.
|
---|
399 | 2655c2655
|
---|
400 | < `ValueTraits` have the following interface:
|
---|
401 | ---
|
---|
402 | > `ValueTraits` has the following interface:
|
---|
403 | 2681c2681
|
---|
404 | < * [*['node_traits]]: The node configuration that it's needed by node algorithms.
|
---|
405 | ---
|
---|
406 | > * [*['node_traits]]: The node configuration that is needed by node algorithms.
|
---|
407 | 2683c2683
|
---|
408 | < described in the previous chapter: [link intrusive.node_algorithms Nodes Algorithms].
|
---|
409 | ---
|
---|
410 | > described in the previous chapter: [link intrusive.node_algorithms Node Algorithms].
|
---|
411 | 2711c2711
|
---|
412 | < as `node_ptr`: If `node_ptr` is `node *` `pointer` must be `value_type*`. If
|
---|
413 | ---
|
---|
414 | > as `node_ptr`: If `node_ptr` is `node*`, `pointer` must be `value_type*`. If
|
---|
415 | 2717c2717
|
---|
416 | < as `node_ptr`: If `node_ptr` is `node *` `const_pointer` must be `const value_type*`. If
|
---|
417 | ---
|
---|
418 | > as `node_ptr`: If `node_ptr` is `node*`, `const_pointer` must be `const value_type*`. If
|
---|
419 | 2727c2727
|
---|
420 | < as the link, containers
|
---|
421 | ---
|
---|
422 | > as the link mode, containers
|
---|
423 | 2731d2730
|
---|
424 | < normal_link,
|
---|
425 | 2733,2735c2732,2734
|
---|
426 | < * [*`safe_link`]: If this linking policy is specified in a `ValueTraits` class
|
---|
427 | < as the link, containers
|
---|
428 | < configured with such `ValueTraits` will set the hooks
|
---|
429 | ---
|
---|
430 | > * [*`safe_link`]: If this linking policy is specified as the link mode
|
---|
431 | > in a `ValueTraits` class, containers
|
---|
432 | > configured with this `ValueTraits` will set the hooks
|
---|
433 | 2742c2741
|
---|
434 | < Containers also know that the a value can be silently erased from
|
---|
435 | ---
|
---|
436 | > Containers also know that a value can be silently erased from
|
---|
437 | 2747c2746
|
---|
438 | < These function take a reference to a value_type and return a pointer to the node
|
---|
439 | ---
|
---|
440 | > These functions take a reference to a value_type and return a pointer to the node
|
---|
441 | 2752c2751
|
---|
442 | < These function take a pointer to a node and return a pointer to the value
|
---|
443 | ---
|
---|
444 | > These functions take a pointer to a node and return a pointer to the value
|
---|
445 | 2764c2763
|
---|
446 | < the object in a singly and doubly linked list at the same time.
|
---|
447 | ---
|
---|
448 | > the object in both a singly and a doubly linked list at the same time.
|
---|
449 | 2776c2775
|
---|
450 | < Defining a value traits class that just defines `value_type` as
|
---|
451 | ---
|
---|
452 | > Defining a value traits class that simply defines `value_type` as
|
---|
453 | 2797c2796
|
---|
454 | < if the user does not want to use provided [*Boost.Intrusive] facilities.
|
---|
455 | ---
|
---|
456 | > if the user does not want to use the provided [*Boost.Intrusive] facilities.
|
---|
457 | 2817c2816
|
---|
458 | < we'll define a templatized `ValueTraits` that will work for both types:
|
---|
459 | ---
|
---|
460 | > a templatized `ValueTraits` that will work for both types:
|
---|
461 | 2828c2827
|
---|
462 | < all the possible [classref boost::intrusive::list list] containers
|
---|
463 | ---
|
---|
464 | > all possible [classref boost::intrusive::list list] containers
|
---|
465 | 2836c2835
|
---|
466 | < The previous example can be further simplified using
|
---|
467 | ---
|
---|
468 | > The previous example can be further simplified using the
|
---|
469 | 2872,2873c2871,2872
|
---|
470 | < so that we can even separate nodes and values and [*avoid modifying types to insert nodes].
|
---|
471 | < [*Boost.Intrusive] differentiates between stateful and stateless value traits checking if the ValueTraits
|
---|
472 | ---
|
---|
473 | > so that we can separate nodes and values and [*avoid modifying types to insert nodes].
|
---|
474 | > [*Boost.Intrusive] differentiates between stateful and stateless value traits by checking if the ValueTraits
|
---|
475 | 2883c2882
|
---|
476 | < (stateless value traits could use global variables to achieve the same property), so:
|
---|
477 | ---
|
---|
478 | > (stateless value traits could use global variables to achieve the same goal), so:
|
---|
479 | 2886,2887c2885,2886
|
---|
480 | < value traits, since accessing to global resources might require syncronization primitives that
|
---|
481 | < can be avoided when using the internal state.
|
---|
482 | ---
|
---|
483 | > value traits, since accessing global resources might require syncronization primitives that
|
---|
484 | > can be avoided when using internal state.
|
---|
485 | 2889c2888
|
---|
486 | < * [*Run-time polimorphism]: A value traits might implement node <-> value
|
---|
487 | ---
|
---|
488 | > * [*Run-time polymorphism]: A value traits might implement node <-> value
|
---|
489 | 2896c2895
|
---|
490 | < [*A heavy node <-> value transformation can downgrade intrusive containers' performance].
|
---|
491 | ---
|
---|
492 | > [*A heavy node <-> value transformation will hurt intrusive containers' performance].
|
---|
493 | 2917c2916
|
---|
494 | < Intrusive containers have similar same thread-safety guarantees than STL containers.
|
---|
495 | ---
|
---|
496 | > Intrusive containers have thread safety guarantees similar to STL containers.
|
---|
497 | 2919c2918
|
---|
498 | < * Several threads can have read or write access to different instances is safe as long as inserted
|
---|
499 | ---
|
---|
500 | > * Several threads having read or write access to different instances is safe as long as inserted
|
---|
501 | 2926,2927c2925,2926
|
---|
502 | < Other functions, like checking if an objects is already inserted in a containers using the `is_linked()`
|
---|
503 | < member of safe hooks is a read-access to the container without having a reference to them, so no other
|
---|
504 | ---
|
---|
505 | > Other functions, like checking if an object is already inserted in a container using the `is_linked()`
|
---|
506 | > member of safe hooks, constitute read access on the container without having a reference to it, so no other
|
---|
507 | 2931c2930
|
---|
508 | < the thread safety of [*Boost.Intrusive] is related to the containers and also the object whose lifetime
|
---|
509 | ---
|
---|
510 | > the thread safety of [*Boost.Intrusive] is related to the containers and also to the object whose lifetime
|
---|
511 | 2937c2936
|
---|
512 | < To analyze the thread-safety, take in care the following points:
|
---|
513 | ---
|
---|
514 | > To analyze the thread safety, consider the following points:
|
---|
515 | 2939,2941c2938,2940
|
---|
516 | < * Auto-unlink hook's destructor and `unlink()` functions modify the container indirectly.
|
---|
517 | < * Safe mode and auto-unlink hook's `is_linked()` function is a read access to the container.
|
---|
518 | < * Inserting an object in several containers that will be modified by different threads has no thread-safety
|
---|
519 | ---
|
---|
520 | > * The auto-unlink hook's destructor and `unlink()` functions modify the container indirectly.
|
---|
521 | > * The safe mode and auto-unlink hooks' `is_linked()` functions are a read access to the container.
|
---|
522 | > * Inserting an object in containers that will be modified by different threads has no thread safety
|
---|
523 | 2949c2948
|
---|
524 | < has also a couple of downsides:
|
---|
525 | ---
|
---|
526 | > has a couple of downsides:
|
---|
527 | 2951,2954c2950,2953
|
---|
528 | < * If a user specifies the same options in different order or specifies some options and lefts the
|
---|
529 | < rest as defaults the type of the created container/hook will be different. Sometimes
|
---|
530 | < this is annoying, because two programmers specifying the same options might end with incompatible
|
---|
531 | < types. For example, the following two lists, although they're using the same options, have not
|
---|
532 | ---
|
---|
533 | > * If a user specifies the same options in different order or specifies some options and leaves the
|
---|
534 | > rest as defaults, the type of the created container/hook will be different. Sometimes
|
---|
535 | > this is annoying, because two programmers specifying the same options might end up with incompatible
|
---|
536 | > types. For example, the following two lists, although using the same options, do not have
|
---|
537 | 2972c2971
|
---|
538 | < might suffer a bit if long names are produced.
|
---|
539 | ---
|
---|
540 | > may suffer if long names are produced.
|
---|
541 | 2974,2977c2973,2976
|
---|
542 | < To solve these issues [*Boost.Intrusive] offers some helper metafunctions that that reduce symbol lengths
|
---|
543 | < and create the same type if the same options (either explicitly or implicitly) are used. This also
|
---|
544 | < improves compilation times. All containers and hooks have their respective `make_xxx` versions.
|
---|
545 | < Previous shown example can be rewritten like this to obtain the same list type:
|
---|
546 | ---
|
---|
547 | > To solve these issues [*Boost.Intrusive] offers some helper metafunctions that reduce symbol lengths
|
---|
548 | > and create the same type if the same options (either explicitly or implicitly) are used. These also
|
---|
549 | > improve compilation times. All containers and hooks have their respective `make_xxx` versions.
|
---|
550 | > The previously shown example can be rewritten like this to obtain the same list type:
|
---|
551 | 2995,2996c2994,2995
|
---|
552 | < Produced symbol lengths and compilation times are usually shorter and object/debug files are smaller.
|
---|
553 | < If you are a programmer concerned with file sizes and compilation times, this option is your choice.
|
---|
554 | ---
|
---|
555 | > Produced symbol lengths and compilation times will usually be shorter and object/debug files smaller.
|
---|
556 | > If you are concerned with file sizes and compilation times, this option is your best choice.
|
---|
557 | 3025c3024
|
---|
558 | < [*Boost.Intrusive] wants to avoid any code size overhead associated with templates.
|
---|
559 | ---
|
---|
560 | > [*Boost.Intrusive] seeks to avoid any code size overhead associated with templates.
|
---|
561 | 3029,3030c3028,3029
|
---|
562 | < are two-byte aligned. The possibility to avoid constant-time size operations can
|
---|
563 | < save some size on containers, and this extra size optimization is noticeable
|
---|
564 | ---
|
---|
565 | > are two-byte aligned. The option to forgo constant-time size operations can
|
---|
566 | > reduce container size, and this extra size optimization is noticeable
|
---|
567 | 3035c3034
|
---|
568 | < [section: Boost.Intrusive as basic building block]
|
---|
569 | ---
|
---|
570 | > [section: Boost.Intrusive as a basic building block]
|
---|
571 | 3037,3039c3036,3038
|
---|
572 | < [*Boost.Intrusive] should be a basic building block to build more complex containers
|
---|
573 | < and this guideline has motivated many design decisions. For example, the possibility
|
---|
574 | < to have more than one hook per user type opens the possibility to implement multi-index
|
---|
575 | ---
|
---|
576 | > [*Boost.Intrusive] can be a basic building block to build more complex containers
|
---|
577 | > and this potential has motivated many design decisions. For example, the ability
|
---|
578 | > to have more than one hook per user type opens the opportunity to implement multi-index
|
---|
579 | 3043,3044c3042,3043
|
---|
580 | < as arguments (`clone_from`, `erase_and_dispose`, `insert_check`...). These
|
---|
581 | < functions come handy when implementing non-intrusive containers
|
---|
582 | ---
|
---|
583 | > as arguments (`clone_from`, `erase_and_dispose`, `insert_check`, etc.). These
|
---|
584 | > functions come in handy when implementing non-intrusive containers
|
---|
585 | 3054c3053
|
---|
586 | < build special hooks that take advantage of its application environment.
|
---|
587 | ---
|
---|
588 | > build special hooks that take advantage of an application environment.
|
---|
589 | 3056c3055
|
---|
590 | < For example, the programmer can use can customize parts of [*Boost.Intrusive]
|
---|
591 | ---
|
---|
592 | > For example, the programmer can customize parts of [*Boost.Intrusive]
|
---|
593 | 3065,3066c3064,3065
|
---|
594 | < [*Boost.Intrusive] containers offer speed improvements comparing to non-intrusive containers,
|
---|
595 | < basically because:
|
---|
596 | ---
|
---|
597 | > [*Boost.Intrusive] containers offer speed improvements compared to non-intrusive containers
|
---|
598 | > primarily because:
|
---|
599 | 3068,3069c3067,3068
|
---|
600 | < * We can minimize memory allocation/deallocation calls.
|
---|
601 | < * We obtain better memory locality.
|
---|
602 | ---
|
---|
603 | > * They minimize memory allocation/deallocation calls.
|
---|
604 | > * They obtain better memory locality.
|
---|
605 | 3071c3070
|
---|
606 | < This section will show some performance tests comparing some operations on
|
---|
607 | ---
|
---|
608 | > This section will show performance tests comparing some operations on
|
---|
609 | 3076c3075
|
---|
610 | < * `reverse` member function will show the advantages of the compact
|
---|
611 | ---
|
---|
612 | > * The `reverse` member function will show the advantages of the compact
|
---|
613 | 3078,3079c3077,3078
|
---|
614 | < * `sort` and `write access` tests will show the advantage of intrusive containers
|
---|
615 | < minimizing the memory accesses when comparing them with containers of pointers.
|
---|
616 | ---
|
---|
617 | > * The `sort` and `write access` tests will show the advantage of intrusive containers
|
---|
618 | > minimizing memory accesses compared to containers of pointers.
|
---|
619 | 3083c3082
|
---|
620 | < or it can replace `std::list<T*>` when the user wants to obtain containers with
|
---|
621 | ---
|
---|
622 | > or it can replace `std::list<T*>` when the user wants containers with
|
---|
623 | 3115c3114
|
---|
624 | < `test_list` objects to funtion objects taking pointers to them.
|
---|
625 | ---
|
---|
626 | > `test_list` objects to function objects taking pointers to them.
|
---|
627 | 3123c3122
|
---|
628 | < avoiding memory allocations and deallocations . All the objects to be
|
---|
629 | ---
|
---|
630 | > avoiding memory allocations and deallocations. All the objects to be
|
---|
631 | 3125c3124
|
---|
632 | < whereas `std::list` will need to allocate memory for every and deallocate it
|
---|
633 | ---
|
---|
634 | > whereas `std::list` will need to allocate memory for each object and deallocate it
|
---|
635 | 3183,3184c3182,3183
|
---|
636 | < whereas `safe_link` and `auto_unlink` intrusive containers need to put the hook of
|
---|
637 | < erased values' in the default state (complexity: `O(NumElements)`). That's why
|
---|
638 | ---
|
---|
639 | > whereas `safe_link` and `auto_unlink` intrusive containers need to put the hooks of
|
---|
640 | > erased values in the default state (complexity: `O(NumElements)`). That's why
|
---|
641 | 3187,3188c3186,3187
|
---|
642 | < Non-intrusive containers need to make much more allocations and that's why they are
|
---|
643 | < lagging behind. The `disperse pointer list` needs to make `NumElements*2` allocations,
|
---|
644 | ---
|
---|
645 | > Non-intrusive containers need to make many more allocations and that's why they
|
---|
646 | > lag behind. The `disperse pointer list` needs to make `NumElements*2` allocations,
|
---|
647 | 3191,3193c3190,3192
|
---|
648 | < Linux test shows that standard containers perform very well against intrusive containers
|
---|
649 | < with big objects. Nearly the same GCC version in MinGW performs worse, so maybe the
|
---|
650 | < a good memory allocator is the reason for these excelent results.
|
---|
651 | ---
|
---|
652 | > The Linux test shows that standard containers perform very well against intrusive containers
|
---|
653 | > with big objects. Nearly the same GCC version in MinGW performs worse, so maybe
|
---|
654 | > a good memory allocator is the reason for these excellent results.
|
---|
655 | 3200c3199
|
---|
656 | < Values (`test_class` and `itest_class`) and lists are created like explained in the
|
---|
657 | ---
|
---|
658 | > Values (`test_class` and `itest_class`) and lists are created as explained in the
|
---|
659 | 3205c3204
|
---|
660 | < since this function just needs to adjust internal pointers, so in theory, all tested
|
---|
661 | ---
|
---|
662 | > since this function just needs to adjust internal pointers, so in theory all tested
|
---|
663 | 3263,3265c3262,3264
|
---|
664 | < For big values the compact pointer list wins because when reversing doesn't need access
|
---|
665 | < to the values stored in another container. Since all the allocations for nodes of
|
---|
666 | < this pointer list are likely to be near (since there is no other allocation in the
|
---|
667 | ---
|
---|
668 | > For big objects the compact pointer list wins because the reversal test doesn't need access
|
---|
669 | > to values stored in another container. Since all the allocations for nodes of
|
---|
670 | > this pointer list are likely to be close (since there is no other allocation in the
|
---|
671 | 3267c3266
|
---|
672 | < containers. The dispersed pointer list, like with small values, has poor locality.
|
---|
673 | ---
|
---|
674 | > containers. The dispersed pointer list, as with small values, has poor locality.
|
---|
675 | 3273,3274c3272,3273
|
---|
676 | < The next test measures the time needed to complete calls the member function
|
---|
677 | < `sort(Pred pred)`. Values (`test_class` and `itest_class`) and lists are created like explained in the
|
---|
678 | ---
|
---|
679 | > The next test measures the time needed to complete calls to the member function
|
---|
680 | > `sort(Pred pred)`. Values (`test_class` and `itest_class`) and lists are created as explained in the
|
---|
681 | 3301c3300
|
---|
682 | < another container to compare to elements.
|
---|
683 | ---
|
---|
684 | > another container to compare two elements.
|
---|
685 | 3338,3341c3337,3340
|
---|
686 | < indirection that needs to access the value is minimized because all the values
|
---|
687 | < are tightly stored, improving cache. The disperse list, on the other hand, is
|
---|
688 | < slower because the indirection to access to values stored in the object list is
|
---|
689 | < more expensive than the access to values stored in a vector.
|
---|
690 | ---
|
---|
691 | > indirection that is needed to access the value is minimized because all the values
|
---|
692 | > are tightly stored, improving caching. The disperse list, on the other hand, is
|
---|
693 | > slower because the indirection to access values stored in the object list is
|
---|
694 | > more expensive than accessing values stored in a vector.
|
---|
695 | 3347c3346
|
---|
696 | < The next test measures the time needed to iterate all the elements of a list, and
|
---|
697 | ---
|
---|
698 | > The next test measures the time needed to iterate through all the elements of a list, and
|
---|
699 | 3356c3355
|
---|
700 | < Values (`test_class` and `itest_class`) and lists are created like explained in
|
---|
701 | ---
|
---|
702 | > Values (`test_class` and `itest_class`) and lists are created as explained in
|
---|
703 | 3399c3398
|
---|
704 | < Like with the read access test, the results show that intrusive containers outperform
|
---|
705 | ---
|
---|
706 | > As with the read access test, the results show that intrusive containers outperform
|
---|
707 | 3401c3400
|
---|
708 | < The disperse list is again the slowest one.
|
---|
709 | ---
|
---|
710 | > The disperse list is again the slowest.
|
---|
711 | 3409c3408
|
---|
712 | < when objects to be inserted are small. Minimizing memory allocation/deallocation calls is also
|
---|
713 | ---
|
---|
714 | > when the objects to be inserted are small. Minimizing memory allocation/deallocation calls is also
|
---|
715 | 3434c3433
|
---|
716 | < [*Boost.Intrusive] has been tested in the following compilers/platforms:
|
---|
717 | ---
|
---|
718 | > [*Boost.Intrusive] has been tested on the following compilers/platforms:
|
---|
719 | 3451c3450
|
---|
720 | < [*Boost.Intrusive] is based on STL concepts and interface.
|
---|
721 | ---
|
---|
722 | > [*Boost.Intrusive] is based on STL concepts and interfaces.
|
---|
723 | 3485c3484
|
---|
724 | < * Thanks to of [*Julienne Walker] and [*The EC Team] ([@http://eternallyconfuzzled.com])
|
---|
725 | ---
|
---|
726 | > * Thanks to [*Julienne Walker] and [*The EC Team] ([@http://eternallyconfuzzled.com])
|
---|