Struct Backdrop

Source
pub struct Backdrop<T, S: BackdropStrategy<T>> { /* private fields */ }
Expand description

Wrapper to drop any value at a later time, such as in a background thread.

Backdrop<T, Strategy> is guaranteed to have the same in-memory representation as T. As such, wrapping (and unwrapping) a T into a Backdrop<T, S> has zero memory overhead.

Besides altering how T is dropped, a Backdrop<T, S> behaves as much as possible as a T. This is done by implementing Deref and DerefMut so most methods available for T are also immediately available for Backdrop<T>. Backdrop<T, S> also implements many common traits whenever T implements these.

§Customizing the strategy

You customize what strategy is used by picking your desired S parameter, which can be any type that implements the BackdropStrategy trait. This crate comes with many common strategies, but you can also implement your own.

§Restrictions

Backdrop<T, Strategy> does not restrict T (besides T needing to be Sized). However, Many Strategy only implement BackdropStrategy<T> when T fits certain restrictions. For instance, the TrashThreadStrategy requires T to be Send since T will be moved to another thread to be cleaned up there.

What about unsized/dynamically-sized types? The current implementation of Backdrop restricts T to be Sized mostly for ease of implementation. It is our expectation that your unsized datastructures probably are already nested in a std::boxed::Box<T> or other smart pointer, which you can wrap with Backdrop as a whole. (Side note: Zero-sized types can be wrapped by Backdrop without problems.)

There is one final important restriction:

§The problem with Arc

A Backdrop<Arc<T>, S> will not behave as you might expect: It will cause the backdrop strategy to run whenever the reference count is decremented. But what you probably want, is to run the backdrop strategy exactly when the last Arc<T> is dropped (AKA when the reference count drops to 0) and the contents of the Arc go out of scope.

A Arc<Backdrop<Box<T>, S>> will work as you expect, but you incur an extra pointer indirection (arc -> box -> T) every time you read its internal value.

Instead, use the backdrop_arc crate, which contains a specialized Arc datatype that does exactly what you want without a needless indirection.

Implementations§

Source§

impl<T, Strategy: BackdropStrategy<T>> Backdrop<T, Strategy>

Source

pub fn new(val: T) -> Self

Construct a new Backdrop<T, S> from any T. This is a zero-cost operation.

From now on, T will no longer be dropped normally, but instead it will be dropped using the implementation of the given BackdropStrategy.

use backdrop::*;

// Either specify the return type:
let mynum: Backdrop<usize, LeakStrategy> = Backdrop::new(42);

// Or use the 'Turbofish' syntax on the function call:
let mynum2 = Backdrop::<_, LeakStrategy>::new(42);

// Or use one of the shorthand type aliases:
let mynum3 = LeakBackdrop::new(42);

assert_eq!(mynum, mynum2);
assert_eq!(mynum2, mynum3);
// <- Because we are using the LeakStrategy, we leak memory here. Fun! :-)

This function is the inverse of Backdrop::into_inner.

Examples found in repository?
examples/comparison.rs (line 27)
19fn main() {
20    let boxed = setup();
21    let not_backdropped = boxed.clone();
22    time("none", move || {
23        assert_eq!(not_backdropped.len(), LEN);
24        // Destructor runs here
25    });
26
27    let backdropped: TrivialBackdrop<_> = Backdrop::new(boxed.clone());
28    time("fake backdrop", move || {
29        assert_eq!(backdropped.len(), LEN);
30        // Destructor runs here
31    });
32
33    let backdropped: thread::ThreadBackdrop<_> = Backdrop::new(boxed.clone());
34    time("thread backdrop", move || {
35        assert_eq!(backdropped.len(), LEN);
36        // Destructor runs here
37    });
38
39    TrashThreadStrategy::with_trash_thread(||{
40        let backdropped: thread::TrashThreadBackdrop<_> = Backdrop::new(boxed.clone());
41        time("trash thread backdrop", move || {
42            assert_eq!(backdropped.len(), LEN);
43            // Destructor runs here
44        });
45    });
46
47    TrashQueueStrategy::ensure_initialized();
48    let backdropped = Backdrop::<_, TrashQueueStrategy>::new(boxed.clone());
49    time("(single threaded) trash queue backdrop", move || {
50        assert_eq!(backdropped.len(), LEN);
51        // Destructor runs here
52    });
53
54    time("(single threaded) trash queue backdrop (actually cleaning up later)", move || {
55        TrashQueueStrategy::cleanup_all();
56    });
57
58    #[cfg(miri)]
59    {
60        println!("Skipping Tokio examples when running on Miri, since it does not support Tokio yet");
61    }
62    #[cfg(not(miri))]
63    {
64    ::tokio::runtime::Builder::new_multi_thread()
65        .enable_all()
66        .build()
67        .unwrap()
68        .block_on(async {
69            let backdropped: crate::tokio::TokioTaskBackdrop<_> = Backdrop::new(boxed.clone());
70            time("tokio task (multithread runner)", move || {
71                assert_eq!(backdropped.len(), LEN);
72                // Destructor runs here
73            });
74
75            let backdropped: crate::tokio::TokioBlockingTaskBackdrop<_> = Backdrop::new(boxed.clone());
76            time("tokio blocking task (multithread runner)", move || {
77                assert_eq!(backdropped.len(), LEN);
78                // Destructor runs here
79            });
80        });
81
82    ::tokio::runtime::Builder::new_current_thread()
83        .enable_all()
84        .build()
85        .unwrap()
86        .block_on(async {
87            let backdropped: crate::tokio::TokioTaskBackdrop<_> = Backdrop::new(setup());
88            time("tokio task (current thread runner)", move || {
89                assert_eq!(backdropped.len(), LEN);
90                // Destructor runs here
91            });
92
93            let backdropped: crate::tokio::TokioBlockingTaskBackdrop<_> = Backdrop::new(setup());
94            time("tokio blocking task (current thread runner)", move || {
95                assert_eq!(backdropped.len(), LEN);
96                // Destructor runs here
97            });
98        });
99    }
100}
Source

pub fn into_inner(this: Self) -> T

Turns a Backdrop<T, S> back into a normal T. This undoes the effect of Backdrop. The resulting T will be dropped again using normal rules. This function is the inverse of Backdrop::new.

This is a zero-cost operation.

This is an associated function, so call it using fully-qualified syntax.

Source

pub fn change_strategy<S2: BackdropStrategy<T>>(this: Self) -> Backdrop<T, S2>

Changes the strategy used for a Backdrop.

This is a zero-cost operation

This is an associated function, so call it using fully-qualified syntax.

use backdrop::*;

let foo = LeakBackdrop::new(42);
let foo = Backdrop::change_strategy::<TrivialStrategy>(foo);
// Now `foo` will be dropped according to TrivialStrategy (which does the normal drop rules)
// rather than LeakStrategy (which does not cleanup by leaking memory)

Trait Implementations§

Source§

impl<T: Archive, S> Archive for Backdrop<T, S>
where S: BackdropStrategy<T>,

Available on crate feature rkyv only.
Source§

type Archived = <T as Archive>::Archived

The archived representation of this type. Read more
Source§

type Resolver = <T as Archive>::Resolver

The resolver for this type. It must contain all the additional information from serializing needed to make the archived type from the normal type.
Source§

unsafe fn resolve( &self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived, )

Creates the archived version of this value at the given position and writes it to the given output. Read more
Source§

impl<C: ?Sized, T: CheckBytes<C>, S> CheckBytes<C> for Backdrop<T, S>
where S: BackdropStrategy<T>,

Available on crate feature bytecheck only.
Source§

type Error = <T as CheckBytes<C>>::Error

The error that may result from checking the type.
Source§

unsafe fn check_bytes<'a>( value: *const Self, context: &mut C, ) -> Result<&'a Self, Self::Error>

Checks whether the given pointer points to a valid value within the given context. Read more
Source§

impl<T: Clone, S> Clone for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, S> Debug for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, S: BackdropStrategy<T>> DerefMut for Backdrop<T, S>

Source§

fn deref_mut(&mut self) -> &mut T

Mutably dereferences the value.
Source§

impl<Des, T, S> Deserialize<Backdrop<T, S>, Des> for Archived<T>
where T: Archive, Archived<T>: Deserialize<T, Des>, Des: Fallible, S: BackdropStrategy<T>,

Available on crate feature rkyv only.
Source§

fn deserialize( &self, deserializer: &mut Des, ) -> Result<Backdrop<T, S>, <Des as Fallible>::Error>

Deserializes using the given deserializer
Source§

impl<T: Display, S> Display for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, Strategy: BackdropStrategy<T>> Drop for Backdrop<T, Strategy>

This is where the magic happens: Instead of dropping T normally, we run Strategy::execute on it.

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T, S> From<T> for Backdrop<T, S>
where S: BackdropStrategy<T>,

Converting between a T and a Backdrop<T, S> is a zero-cost operation

Source§

fn from(val: T) -> Self

Converts to this type from the input type.
Source§

impl<T: Hash, S> Hash for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<T: Ord, S> Ord for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<T: PartialEq, S> PartialEq for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: PartialOrd, S> PartialOrd for Backdrop<T, S>
where S: BackdropStrategy<T>,

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<Ser, T: Archive + Serialize<Ser>, S> Serialize<Ser> for Backdrop<T, S>
where Ser: Fallible, S: BackdropStrategy<T>,

Available on crate feature rkyv only.
Source§

fn serialize( &self, serializer: &mut Ser, ) -> Result<Self::Resolver, <Ser as Fallible>::Error>

Writes the dependencies for the object and returns a resolver that can create the archived type.
Source§

impl<T, S: BackdropStrategy<T>> Deref for Backdrop<T, S>

Source§

type Target = T

The resulting type after dereferencing.
Source§

fn deref(&self) -> &T

Dereferences the value.
Source§

impl<T: Eq, S> Eq for Backdrop<T, S>
where S: BackdropStrategy<T>,

Auto Trait Implementations§

§

impl<T, S> Freeze for Backdrop<T, S>
where T: Freeze,

§

impl<T, S> RefUnwindSafe for Backdrop<T, S>

§

impl<T, S> Send for Backdrop<T, S>
where T: Send, S: Send,

§

impl<T, S> Sync for Backdrop<T, S>
where T: Sync, S: Sync,

§

impl<T, S> Unpin for Backdrop<T, S>
where T: Unpin, S: Unpin,

§

impl<T, S> UnwindSafe for Backdrop<T, S>
where T: UnwindSafe, S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> ArchiveUnsized for T
where T: Archive,

Source§

type Archived = <T as Archive>::Archived

The archived counterpart of this type. Unlike Archive, it may be unsized. Read more
Source§

type MetadataResolver = ()

The resolver for the metadata of this type. Read more
Source§

unsafe fn resolve_metadata( &self, _: usize, _: <T as ArchiveUnsized>::MetadataResolver, _: *mut <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata, )

Creates the archived version of the metadata for this value at the given position and writes it to the given output. Read more
Source§

unsafe fn resolve_unsized( &self, from: usize, to: usize, resolver: Self::MetadataResolver, out: *mut RelPtr<Self::Archived, <isize as Archive>::Archived>, )

Resolves a relative pointer to this value with the given from and to and writes it to the given output. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<F, W, T, D> Deserialize<With<T, W>, D> for F
where W: DeserializeWith<F, T, D>, D: Fallible + ?Sized, F: ?Sized,

Source§

fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>

Deserializes using the given deserializer
Source§

impl<T> From<!> for T

Source§

fn from(t: !) -> T

Converts to this type from the input type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The type for metadata in pointers and references to Self.
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, S> SerializeUnsized<S> for T
where T: Serialize<S>, S: Serializer + ?Sized,

Source§

fn serialize_unsized( &self, serializer: &mut S, ) -> Result<usize, <S as Fallible>::Error>

Writes the object and returns the position of the archived type.
Source§

fn serialize_metadata(&self, _: &mut S) -> Result<(), <S as Fallible>::Error>

Serializes the metadata for the given type.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Error for T
where T: Debug + Display + 'static + Send + Sync,