| 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])
|
|---|