#wrapper #send #thread-local #thread-safe

send_wrapper

这个 Rust 库实现了一个名为 SendWrapper 的包装类型,允许你在线程之间移动非 Send 类型,前提是只从原始线程访问包含的值。你还需要确保在原始线程中丢弃包装器。如果违反了这些约束中的任何一个,都会发生 panic。

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 日

#122Rust 模式

Download history 131816/week @ 2024-04-23 115841/week @ 2024-04-30 138905/week @ 2024-05-07 153960/week @ 2024-05-14 153394/week @ 2024-05-21 166598/week @ 2024-05-28 164895/week @ 2024-06-04 160486/week @ 2024-06-11 157687/week @ 2024-06-18 178415/week @ 2024-06-25 167680/week @ 2024-07-02 163890/week @ 2024-07-09 184924/week @ 2024-07-16 198071/week @ 2024-07-23 173620/week @ 2024-07-30 189433/week @ 2024-08-06

779,803 每月下载
用于 1,165 个 crate (54 直接)

MIT/Apache

21KB
278

SendWrapper

这个 Rust crate 实现了一个名为 SendWrapper 的包装类型,允许你在线程之间移动非 Send 类型,前提是只从原始线程访问包含的值。你还需要确保在原始线程中丢弃包装器。如果违反了这些约束中的任何一个,都会发生 panic。

这个 crate 的想法源于一个基于 GTK+/gtk-rs 的应用程序的上下文。 GTK+ 应用程序是严格单线程的。不允许从除主线程之外的其他线程调用任何 GTK+ 方法。因此,所有 gtk-rs 结构体都是非 Send

有时你仍然想在后台执行一些工作。可以使用 GlibGTK+ 调用排队到主线程执行。这样你可以知道,涉及的 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;

包装 FutureStream

要在 FutureStream 上使用 SendWrapper,您首先应启用 Cargo 功能 futures

send_wrapper = { version = "0.5", features = ["futures"] }

然后,您可以透明地包装您的 FutureStream

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 以获取详细信息。

依赖项