我可以将闭包序列化为 Vec<u8> 然后反序列化并执行它吗?
Can I serialize a closure to Vec<u8> then deserialize and execute it?
我想做这样的伪代码:
let mut vec = Vec<u8>::new();
vec.resize(1024); // Some large-enough size
serialize(&vec, || { .... });
// ... other code blah blah ...
deserialize(&vec); // This will execute the closure
理想情况下,我可以 运行 在另一个线程中反序列化,这才是真正这样做的全部意义所在。
我不想发送操作码和数据,因为这种方式打开了一个非常干净的编程模型,您无需创建消息并发送它们。相反,您只是 运行 在另一个线程中任意复杂的代码。
为什么“非常干净”?
没有需要创建的操作码(消息)。即,更少的代码。
接收端没有opcode dispatch的switch语句。即,更少的代码。
因为没有协议,所以不需要对消息进行版本控制。即,更少的代码。
这个idea不能跨进程使用,但对我的需求来说没问题。
不使用 unsafe
?不不不不
问题在于,由于 Vec<u8>
s 可以被微不足道地修改,你很容易违反 Rust 的安全不变量。考虑以下代码:
let vec = Vec<u8>::new();
vec.resize(1024);
// Our theoretical serialize function.
serialize(&vec, || { /* ... */ });
vec[0] = 0x90; // What happens to the closure now?
deserialize(&vec); // There goes any memory safety...
但是,如果您只想在线程之间发送闭包,请考虑使用类似 std::sync::mpsc
的东西,它支持发送闭包:
use std::thread;
use std::sync::mpsc::channel;
let (tx, rx) = channel();
thread::spawn(move || {
tx.send(|| { "hi" }).unwrap();
});
let f = rx.recv().unwrap();
assert_eq!(f(), "hi");
然而,我的猜测是这实际上不是您想要做的。正如 Netwave 在评论中所说,您很可能实际上想要发送数据和操作标签;例如:
// On one thread...
tx.send((Op::REMOVE_FILE, path));
// and on the other thread...
let (op, path) = rx.recv();
match op {
Op::REMOVE_FILE => remove_file(path),
/* ... */
}
我想做这样的伪代码:
let mut vec = Vec<u8>::new();
vec.resize(1024); // Some large-enough size
serialize(&vec, || { .... });
// ... other code blah blah ...
deserialize(&vec); // This will execute the closure
理想情况下,我可以 运行 在另一个线程中反序列化,这才是真正这样做的全部意义所在。
我不想发送操作码和数据,因为这种方式打开了一个非常干净的编程模型,您无需创建消息并发送它们。相反,您只是 运行 在另一个线程中任意复杂的代码。
为什么“非常干净”?
没有需要创建的操作码(消息)。即,更少的代码。
接收端没有opcode dispatch的switch语句。即,更少的代码。
因为没有协议,所以不需要对消息进行版本控制。即,更少的代码。
这个idea不能跨进程使用,但对我的需求来说没问题。
不使用 unsafe
?不不不不
问题在于,由于 Vec<u8>
s 可以被微不足道地修改,你很容易违反 Rust 的安全不变量。考虑以下代码:
let vec = Vec<u8>::new();
vec.resize(1024);
// Our theoretical serialize function.
serialize(&vec, || { /* ... */ });
vec[0] = 0x90; // What happens to the closure now?
deserialize(&vec); // There goes any memory safety...
但是,如果您只想在线程之间发送闭包,请考虑使用类似 std::sync::mpsc
的东西,它支持发送闭包:
use std::thread;
use std::sync::mpsc::channel;
let (tx, rx) = channel();
thread::spawn(move || {
tx.send(|| { "hi" }).unwrap();
});
let f = rx.recv().unwrap();
assert_eq!(f(), "hi");
然而,我的猜测是这实际上不是您想要做的。正如 Netwave 在评论中所说,您很可能实际上想要发送数据和操作标签;例如:
// On one thread...
tx.send((Op::REMOVE_FILE, path));
// and on the other thread...
let (op, path) = rx.recv();
match op {
Op::REMOVE_FILE => remove_file(path),
/* ... */
}