//! *Corundum* is a crate with an idiomatic persistent memory programming
//! interface and leverages Rust’s type system to statically avoid
//! most common persistent memory programming bugs. Corundum lets programmers
//! develop persistent data structures using familiar Rust constructs and have
//! confidence that they will be free of those bugs.
//!
//! # Statically Prevented Bugs
//! | Common Bugs | Explanation | Approach |
//! | --- | --- | --- |
//! | Inter-Pool Pointers | A pointer in another pool which is unavailable | Type checking pools in persistent pointers. |
//! | P-to-V Pointers | A persistent pointer pointing at volatile memory | Persistent pointers accept only [`PSafe`] types and volatile pointers are `!PSafe`. Only, [`VCell`] allows single-execution P-to-V pointers. |
//! | V-to-P Pointers | A volatile pointer keeping a zero-referenced object alive | Only [`VWeak`] allows V-to-P pointers which is a weak reference and does not keep data alive. |
//! | Unlogged Updates | An unrecoverable update to persistent data | Modifications are enforced to be inside atomic [`transaction`]s. |
//! | Data Race | Updating persistent data simultaneously in two threads | Mutable borrowing is limited to [`PMutex`] which uses a transaction-wide lock to provide both atomicity and isolation. |
//! | Locked Mutex | A persistent mutex remains locked on powerfail | [`PMutex`] uses [`VCell`] which resets at restart. |
//! | Memory Leaks\* | An allocated memory becomes unreachable | Persistent objects, except the root object, cannot cross transaction boundaries, and memory allocation is available only inside a transaction. Therefore, the allocation can survive only if there is a reference from the root object (or a decedent of it) to the data. \* Cyclic references are not prevented in this version, which lead to a memory leak. Please visit [`this link`] for the information on how to manually resolve that issue. |
//!
//! For more technical details on the implementation, please refer to Corundum's
//! academic [paper] and/or watch the [presentation] 📺.
//!
//! [presentation]: https://www.youtube.com/watch?v=yTk7e_3ZEzk
//! [paper]: http://cseweb.ucsd.edu/~mhoseinzadeh/hoseinzadeh-corundum-asplos21.pdf
//! [`this link`]: ./prc/index.html#cyclic-references
//!
//! # Persistent Objects
//!
//! Persistent objects in Corundum are available through persistent pointers:
//! * [`Pbox`]: A pointer type for persistent memory allocation.
//! * [`Prc`]: A single-threaded reference-counting persistent pointer.
//! * [`Parc`]: A thread-safe reference-counting persistent pointer.
//!
//! # Programming Model
//! Persistent memory is available as a file on a DAX-enable file system such as
//! EXT4-DAX or NOVA. These files are called memory pools. Corundum allows
//! memory pool types rather than memory pool objects to enforce pointer safety
//! while compilation. The trait [`MemPool`] provides the necessary
//! functionalities for the pool type.
//!
//! The first step is to open a memory pool file in the program to be able to
//! work with persistent data. The [`default`] module provides a default memory
//! pool type ([`Allocator`]). To open a pool, we can invoke [`open()`]
//! function which [initializes and] returns a reference to the root object of
//! type `T`.
//!
//! Data modification is provided and allowed only through [`transaction`]al
//! interface. None of the persistent pointers is mutably dereferencing for
//! safety. Mutable objects are allowed via interior mutability of any of the
//! following memory cells:
//!
//! * [`PCell`] (or [`PCell`]): An unborrowable, mutable persistent
//! memory location for a value of type `T` in pool `P`.
//! * [`PRefCell`] (or [`PRefCell`]): A mutable persistent memory location
//! with dynamically checked borrow rules for a value of type `T` in pool `P`.
//! * [`PMutex`] (or [`PMutex`]): A mutual exclusion primitive useful for
//! protecting shared persistent data of type `T` in pool `P`.
//!
//! The following example creates a pool file for a linked-list-based stack, and
//! obtains the root object of type `Node`.
//!
//! ```
//! use corundum::default::*;
//!
//! // Aliasing the pool type for convenience
//! type P = Allocator;
//!
//! #[derive(Root)]
//! struct Node {
//! value: i32,
//! next: PRefCell