pub struct Domain<F> { /* private fields */ }
Expand description

Synchronization point between hazard pointers and the writers they guard against.

Every hazard pointer is associated with a domain, and can only guard against reclamation of objects that are retired through that same domain. In other words, you should always ensure that your code uses the same domain to retire objects as it uses to make hazard pointers to read those objects. If it does not, the hazard pointers will provide no meaningful protection. This connection is part of the safety contract for HazardPointer::load.

Domain families

To help aid in determining that the same domain is used for loads and stores, every domain has an associated domain family (F). The family serves no purpose beyond adding a statically checked guide so that obviously-incompatible domains aren’t used. To take advantage of it, your code should define a new zero-sized type that you use every F appears, like so:

#[non_exhaustive]
struct Family;

type Domain = haphazard::Domain<Family>;
type HazardPointer<'domain> = haphazard::HazardPointer<'domain, Family>;
type AtomicPtr<T> = haphazard::AtomicPtr<T, Family>;

This ensures at compile-time that you don’t, for example, use a HazardPointer from the global domain to guard loads from an AtomicPtr that is tied to a custom domain.

This isn’t bullet-proof though! Nothing prevents you from using hazard pointers allocated from one instance of Domain<Family> with an atomic pointer whose writers use a different instance of Domin<Family>. So be careful!

The unique_domain macro provides a mechanism for constructing a domain with a unique domain family that cannot be confused with any other. If you can use it, you should do so, as it gives stronger static guarantees. However, it has the downside that you cannot name the return type (at least without impl Trait in type aliases), which makes it difficult to store in other types.

Reclamation

Domains are the coordination mechanism used for reclamation. When an object is retired into a domain, the retiring thread will (sometimes) scan the domain for objects that are now safe to reclaim (i.e., drop). Objects that cannot yet be reclaimed because there are active readers are left in the domain for a later retire to check again. This means that there is generally a delay between when an object is retired (i.e., marked as deleted) and when it is actually reclaimed (i.e., drop is called). And if there are no more retires, the objects may not be reclaimed until the owning domain is itself dropped.

When using the global domain to guard data access in your data structure, keep in mind that there is no guarantee that retired objects will be cleaned up by the time your data structure is dropped. As a result, you may need to require that the data you store in said data structure be 'static. If you wish to avoid that bound, you’ll need to construct your own Domain for each instance of your data structure so that all the guarded data is reclaimed when your data structure is dropped.

Implementations

Get a handle to the singleton global domain.

Construct a new domain with the given family type.

The type checker protects you from accidentally using a HazardPointer from one domain family (the type F) with an object protected by a domain in a different family. However, it does not protect you from mixing up domains with the same family type. Therefore, prefer creating domains with unique_domain where possible, since it guarantees a unique F for every domain.

See the Domain documentation for more details.

Retire ptr, and reclaim it once it is safe to do so.

T must be Send since it may be reclaimed by a different thread.

Safety
  1. no [HazardPointer] will guard ptr from this point forward.
  2. ptr has not already been retired unless it has been reclaimed since then.
  3. ptr is valid as &T until self is dropped.

Reclaim as many retired objects as possible.

Returns the number of retired objects that were reclaimed.

Trait Implementations

Executes the destructor for this type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.