|
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