6 个版本 (破坏性)
0.6.0 | 2022 年 6 月 5 日 |
---|---|
0.5.0 | 2020 年 10 月 14 日 |
0.4.0 | 2019 年 11 月 18 日 |
0.3.0 | 2019 年 10 月 16 日 |
0.1.0 | 2017 年 9 月 7 日 |
#122 在 Rust 模式
779,803 每月下载
用于 1,165 个 crate (54 直接)
21KB
278 行
SendWrapper
这个 Rust crate 实现了一个名为 SendWrapper
的包装类型,允许你在线程之间移动非 Send
类型,前提是只从原始线程访问包含的值。你还需要确保在原始线程中丢弃包装器。如果违反了这些约束中的任何一个,都会发生 panic。
这个 crate 的想法源于一个基于 GTK+
/gtk-rs
的应用程序的上下文。 GTK+
应用程序是严格单线程的。不允许从除主线程之外的其他线程调用任何 GTK+
方法。因此,所有 gtk-rs
结构体都是非 Send
。
有时你仍然想在后台执行一些工作。可以使用 Glib 将 GTK+
调用排队到主线程执行。这样你可以知道,涉及的 gtk-rs
结构体仅在主线程中访问,也将在那里丢弃。这个 crate 使 gtk-rs
结构体能够离开主线程。
示例
use send_wrapper::SendWrapper;
use std::rc::Rc;
use std::thread;
use std::sync::mpsc::channel;
// This import is important. It allows you to unwrap the value using deref(),
// deref_mut() or Deref coercion.
use std::ops::{Deref, DerefMut};
// Rc is a non-Send type.
let value = Rc::new(42);
// We now wrap the value with `SendWrapper` (value is moved inside).
let wrapped_value = SendWrapper::new(value);
// A channel allows us to move the wrapped value between threads.
let (sender, receiver) = channel();
let t = thread::spawn(move || {
// This would panic (because of dereferencing in wrong thread):
// let value = wrapped_value.deref();
// Move SendWrapper back to main thread, so it can be dropped from there.
// If you leave this out the thread will panic because of dropping from wrong thread.
sender.send(wrapped_value).unwrap();
});
let wrapped_value = receiver.recv().unwrap();
// Now you can use the value again.
let value = wrapped_value.deref();
// alternatives for dereferencing:
// let value = *wrapped_value;
// let value: &NonSendType = &wrapped_value;
// alternatives for mutable dereferencing (value and wrapped_value must be mutable too, then):
// let mut value = wrapped_value.deref_mut();
// let mut value = &mut *wrapped_value;
// let mut value: &mut NonSendType = &mut wrapped_value;
包装 Future
和 Stream
要在 Future
或 Stream
上使用 SendWrapper
,您首先应启用 Cargo 功能 futures
send_wrapper = { version = "0.5", features = ["futures"] }
然后,您可以透明地包装您的 Future
或 Stream
use futures::{executor, future::{self, BoxFuture}};
use send_wrapper::SendWrapper;
// `Rc` is a `!Send` type,
let value = Rc::new(42);
// so this `Future` is `!Send` too as increments `Rc`'s inner counter.
let future = future::lazy(|_| value.clone());
// We now wrap the `future` with `SendWrapper` (value is moved inside),
let wrapped_future = SendWrapper::new(future);
// so now it's `Send` + `Sync` (`BoxFuture` trait object contains `Send` requirement).
let boxed_future: BoxFuture<_> = Box::pin(wrapped_future);
let t = thread::spawn(move || {
// This would panic (because `future` is polled in wrong thread):
// executor::block_on(boxed_future)
});
变更日志
请参阅 CHANGELOG.md
许可证
send_wrapper
在 MIT 许可证和 Apache 许可证(版本 2.0)的条款下分发。
请参阅 LICENSE-APACHE 和 LICENSE-MIT 以获取详细信息。