https://github.com/jimblandy/shared-take-once
`SharedTakeOnce`: a heap-allocated, shared box that can be consumed.
https://github.com/jimblandy/shared-take-once
Last synced: 3 months ago
JSON representation
`SharedTakeOnce`: a heap-allocated, shared box that can be consumed.
- Host: GitHub
- URL: https://github.com/jimblandy/shared-take-once
- Owner: jimblandy
- Created: 2022-08-04T05:24:22.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2022-08-19T23:48:47.000Z (almost 3 years ago)
- Last Synced: 2025-03-17T16:03:28.129Z (3 months ago)
- Language: Rust
- Size: 4.88 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# shared-take-once
`SharedTakeOnce`: a heap-allocated, shared box that can be consumed.
A `SharedTakeOnce` is a reference-counted pointer
to a `T` value stored on the heap,
with a `take` method that consumes the pointer and gives you ownership of the `T`,
if you are the first to call it.
Subsequent calls to `take` return `None`.
The effect is similar to `Rc>>`,
but with less overhead and a nicer API:
A `SharedTakeOnce` is just a heap pointer to a `T` preceded by a reference count.There are two versions: `sync::SharedTakeOnce` and `non_sync::SharedTakeOnce`.
The former implements `Send` and `Sync` while the latter does not.
The difference is analogous to that between `Arc` and `Rc`:
`sync::SharedTakeOnce` uses slightly more expensive atomic operations,
in exchange for being safely shareable between threads.Here's an example that creates two handles to a vector,
and then takes the vector via the second handle:```rust
use shared_take_once::non_sync::SharedTakeOnce;let handle = SharedTakeOnce::new(vec![1, 2, 3]);
let alias = handle.clone();// Take ownership of the vector via alias.
let mut v = alias.take().unwrap();
v.push(4);
println!("{:?}", v); // prints "[1, 2, 3, 4]"// Now the original handle is empty.
assert!(handle.take().is_none());
```You can use `SharedTakeOnce` to share a `FnOnce` closure between
the 'fulfill' and 'reject' callbacks of a `js_sys::Promise`:```rust
use wasm_bindgen::closure::Closure;let vec = vec![1, 2, 3];
let callback = move || { drop(vec); /* can't be run twice */ };// Make two `SharedTakeOnce` handles referring to `closure`.
let handle_1 = SharedTakeOnce::new(closure);
let handle_2 = handle_1.clone();// Each `wasm_bindgen` closure captures one of the handles.
// Only one closure should ever be called, so we can just `unwrap`
// the value returned by `take`.
let fulfill = Closure::once(move |_| handle_1.take().unwrap()());
let reject = Closure::once(move |_| handle_2.take().unwrap()());let _ = promise.then2(&fulfill, &reject);
```