提问人:mike rodent 提问时间:11/15/2023 最后编辑:mike rodent 更新时间:11/15/2023 访问量:42
将对象存储在静态 Box 中,然后作为可变对象进行检索?
Store an object in a static Box and then retrieve as mutable?
问:
这是 PyO3 的情况。因此,Python 调用了一个长时间运行的任务。使用 ZeroMQ 消息传递(进程间消息传递*),用户可以命令暂停任务。在这一点上,我想将“处理框架”对象存储在一个框中,以便用户以后可能会单击“恢复”,这样,回到 Rust 中,在第二次调用时,框架对象可以从这个框中检索,并从它离开的地方再次开始工作。这样做的最大好处是可以保留框架的状态。static
static
令我惊讶的是,Rust 内存中的结构似乎在对 PyO3 函数的 Python 调用之间得以保留,这一事实启发了我尝试这一点。static
这就是我在检测“挂起”命令时“存放”框架的方式:
static SUSPENDED_FRAMEWORK_OPTION: OnceLock<Box<HandlingFramework>> = OnceLock::new();
...
let mut handling_framework = HandlingFramework::new(op_type, index_name, dir_root_path_str, current_app_version, current_index_version, tx_zero_client);
handling_framework.init()?;
let (job_suspended_state, total_word_count, total_ldoc_count) = handling_framework.index_docs()?;
if std::matches!(job_suspended_state, JobSuspendedState::Suspended) {
let _ = SUSPENDED_FRAMEWORK_OPTION.set(Box::new(handling_framework))
}
...这就是我尝试在以后的 PyO3 调用中检索框架的方式:
if op_type == "RESUME".to_string(){
let option_for_framework = SUSPENDED_FRAMEWORK_OPTION.get();
let framework_box_ref = option_for_framework.unwrap();
info!("text_doc_hit_objs_for_processing remaining {}", framework_box_ref.text_doc_hit_objs_for_processing.len());
info!("framework_box_ref type {}", str_type_of(&framework_box_ref));
给framework_box_ref type &alloc::boxed::Box<populate_index::handling_framework::HandlingFramework>
从某种意义上说,这是有道理的,因为我能够获得对检索到的框架中各种对象的读取访问权限。
但是要做任何有用的事情(恢复处理),我需要对框架对象具有可变访问权限。我在那里尝试的一切都失败了,通常是沿着“无法移出共享引用”的思路。
我试过这样的事情:
fn unbox<T>(value: Box<T>) -> T {
*value
}
let mut framework = unbox(*framework_box_ref);
这给出了:
error[E0507]: cannot move out of `*framework_box_ref` which is behind a shared reference
--> src\lib.rs:114:29
|
114 | let mut framework = unbox(*framework_box_ref);
| ^^^^^^^^^^^^^^^^^^ move occurs because `*framework_box_ref` has type `Box<HandlingFramework>`, which does not implement the `Copy` trait
谁能建议如何获得这个可变变量?目前没有实施或...我已经尝试过这些,但是有太多的内部字段没有实现一个或两个。如果需要,我可能会“手动”实现一个或两个,但目前我希望在没有它的情况下获得可变访问......HandlingFramework
Copy
Clone
derive
* 实际上,这不是进程间消息传递,而是线程间消息传递:Rust 代码似乎与调用它的 Python 工作线程在同一个线程中运行。因此,使用另一个 Python 线程来发送消息......
答:
如果没有某种内部可变性,就无法写入 a 中的值,此时您应该使用它而不是 .请注意,无论如何都不能从引用中移动,甚至不能从 ;要做到这一点,你需要一些东西来交换,以便所指对象仍然有效。OnceLock
OnceLock
&mut
目前还不清楚为什么你需要一个。Box
请考虑改用 .您可以使用 Option::take
来“窃取” ,留下的内容。Mutex<Option<_>>
Option
None
static SUSPENDED_FRAMEWORK_OPTION: Mutex<Option<HandlingFramework>> = Mutex::new(None);
// ...
if std::matches!(job_suspended_state, JobSuspendedState::Suspended) {
*SUSPENDED_FRAMEWORK_OPTION.lock().unwrap() = Some(handling_framework);
}
稍后,您可以像这样取出值:
let mut framework = SUSPENDED_FRAMEWORK_OPTION
.lock()
.unwrap()
.take()
.expect("SUSPENDED_FRAMEWORK_OPTION was None");
但是,我强烈建议不要使用这样的全局状态。最好将此值存储在表示框架状态的 Python 对象上,然后您可以从那里获取它,而不需要全局变量。
评论
HandlingFramework
struct
static
static
评论