|
376 | 376 | //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
|
377 | 377 | //! ```
|
378 | 378 | //!
|
379 |
| -//! ## Intrusive, doubly-linked list |
| 379 | +//! ## An intrusive, doubly-linked list |
380 | 380 | //! [linked-list]: #an-intrusive-doubly-linked-list
|
381 | 381 | //!
|
382 | 382 | //! In an intrusive doubly-linked list, the collection does not actually allocate the memory for the
|
383 | 383 | //! nodes itself. Allocation is controlled by the clients, and nodes can live on a stack frame
|
384 | 384 | //! that lives shorter than the collection does provided the nodes are removed from the
|
385 | 385 | //! collection before returning.
|
386 | 386 | //!
|
387 |
| -//! To make this work, every element has pointers to its predecessor and successor in |
388 |
| -//! the list. Elements can only be added when they are pinned, because moving the elements |
389 |
| -//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked |
390 |
| -//! list element will patch the pointers of its predecessor and successor to remove itself |
391 |
| -//! from the list. |
| 387 | +//! The full implementation details of such a data structure are outside the scope of this |
| 388 | +//! documentation, but we will discuss how [`Pin`] can help to do so. |
392 | 389 | //!
|
393 |
| -//! Crucially, we have to be able to rely on [`drop`] being called before an element is invalidated. |
394 |
| -//! If an element could be deallocated or otherwise invalidated without calling [`drop`], the |
395 |
| -//! pointers into it from its neighboring elements would become invalid, which would break the data |
396 |
| -//! structure. |
| 390 | +//! To make such an intrusive data structure work, every element stores pointers to its predecessor |
| 391 | +//! and successor within its own data, rather than having the list structure itself manage those |
| 392 | +//! pointers. Elements can only be added when they are pinned, because moving the elements |
| 393 | +//! around would invalidate the pointers to it which are contained in the element ahead and behind |
| 394 | +//! it. Moreover, the [`Drop`][Drop] implementation of the element types themselves will in some |
| 395 | +//! way patch the pointers of its predecessor and successor elements to remove itself from the list. |
397 | 396 | //!
|
398 |
| -//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data. |
| 397 | +//! Crucially, this means we have to be able to rely on [`drop`] always being called before that |
| 398 | +//! element is invalidated. If an element could be deallocated or otherwise invalidated without |
| 399 | +//! calling [`drop`], the pointers into it which are stored in its neighboring elements would |
| 400 | +//! become invalid, which would break the data structure. |
399 | 401 | //!
|
400 |
| -//! # Subtle details |
401 |
| -//! [subtle-details]: #subtle-details |
| 402 | +//! Therefore, we rely on [the `Drop` guarantee][drop-guarantee] which comes with pinning data, |
| 403 | +//! |
| 404 | +//! # Subtle details and the `Drop` guarantee |
| 405 | +//! [subtle-details]: self#subtle-details-and-the-drop-guarantee |
| 406 | +//! [drop-guarantee]: self#subtle-details-and-the-drop-guarantee |
402 | 407 | //!
|
403 | 408 | //! The purpose of pinning is not *just* to prevent a value from being *moved*, but rather more
|
404 | 409 | //! generally to be able to rely on the pinned value *remaining valid **at a specific place*** in
|
|
425 | 430 | //! This point is subtle but required for intrusive data structures to be implemented soundly.
|
426 | 431 | //!
|
427 | 432 | //! ## `Drop` guarantee
|
428 |
| -//! [drop-guarantee]: self#drop-guarantee |
429 | 433 | //!
|
430 | 434 | //! There needs to be a way for a pinned value to notify any code that is relying on its pinned
|
431 | 435 | //! status that it is about to be destroyed, so that such code can remove its address from their
|
|
482 | 486 | //! address-sensitive types, which are different from merely using [`Pin<P>`] in a generic
|
483 | 487 | //! way.
|
484 | 488 | //!
|
485 |
| -//! ## Implementing [`Drop`] for types with address-sensitive state |
| 489 | +//! ## Implementing [`Drop`] for types with address-sensitive states |
486 | 490 | //! [drop-impl]: self#implementing-drop-for-types-with-address-sensitive-states
|
487 | 491 | //!
|
488 | 492 | //! The [`drop`] function takes [`&mut self`], but this is called *even if that `self` has been
|
|
0 commit comments