#send #cell #failure #non-send #send-wrapper

fragile

Provides wrapper types for sending non-send values to other threads

4 releases (2 breaking)

0.3.0 Aug 22, 2018
0.2.1 Jun 21, 2018
0.2.0 Jun 21, 2018
0.1.0 Jun 20, 2018

#44 in Rust patterns

Download history 528/week @ 2018-08-05 453/week @ 2018-08-12 687/week @ 2018-08-19 821/week @ 2018-08-26 903/week @ 2018-09-02 1291/week @ 2018-09-09 1251/week @ 2018-09-16 718/week @ 2018-09-23 949/week @ 2018-09-30 969/week @ 2018-10-07 814/week @ 2018-10-14 825/week @ 2018-10-21 959/week @ 2018-10-28

1,412 downloads per month
Used in 29 crates (6 directly)

Apache-2.0

34KB
767 lines

Fragile

This library provides wrapper types that permit sending non Send types to other threads and use runtime checks to ensure safety.

It provides two types: Fragile<T> and Sticky<T> which are similar in nature but have different behaviors with regards to how destructors are executed. The former will panic if the destructor is called in another thread, the latter will temporarily leak the object until the thread shuts down.

use std::thread;

// creating and using a fragile object in the same thread works
let val = Fragile::new(true);
assert_eq!(*val.get(), true);
assert!(val.try_get().is_ok());

// once send to another thread it stops working
thread::spawn(move || {
    assert!(val.try_get().is_err());
}).join()
    .unwrap();

lib.rs:

This library provides wrapper types that permit sending non Send types to other threads and use runtime checks to ensure safety.

It provides three types: Fragile<T> and Sticky<T> which are similar in nature but have different behaviors with regards to how destructors are executed and the extra SemiSticky<T> type which uses Sticky<T> if the value has a destructor and Fragile<T> if it does not.

Both types wrap a value and provide a Send bound. Neither of the types permit access to the enclosed value unless the thread that wrapped the value is attempting to access it. The difference between the two types starts playing a role once destructors are involved.

A Fragile<T> will actually send the T from thread to thread but will only permit the original thread to invoke the destructor. If the value gets dropped in a different thread, the destructor will panic.

A Sticky<T> on the other hand does not actually send the T around but keeps it stored in the original thread's thread local storage. If it gets dropped in the originating thread it gets cleaned up immediately, otherwise it leaks until the thread shuts down naturally.

Example usage

use std::thread;
use fragile::Fragile;

// creating and using a fragile object in the same thread works
let val = Fragile::new(true);
assert_eq!(*val.get(), true);
assert!(val.try_get().is_ok());

// once send to another thread it stops working
thread::spawn(move || {
    assert!(val.try_get().is_err());
}).join()
    .unwrap();

Why?

Most of the time trying to use this crate is going to indicate some code smell. But there are situations where this is useful. For instance you might have a bunch of non Send types but want to work with a Send error type. In that case the non sendable extra information can be contained within the error and in cases where the error did not cross a thread boundary yet extra information can be obtained.

No runtime deps