将对象存储在静态 Box 中,然后将其作为可变对象检索?

问题描述 投票:0回答:1

这是 PyO3 的情况。所以Python调用了一个长时间运行的任务。使用 ZeroMQ 消息传递(进程间消息传递*),用户可以命令暂停任务。此时,我想将“处理框架”对象存储在

static
框中,以便用户稍后可能单击“恢复”,通过这样做,回到 Rust,在第二次调用时,框架对象可以从这个
static
盒子中取出,并从上次停止的地方再次开始工作。这样做的最大优点是可以保留框架的状态。

令我惊讶的是,Rust 内存中的

static
结构似乎在 Python 对 PyO3 函数的调用之间得到了保留,这一事实激励我尝试这一点。

这就是我在检测“挂起”命令时“存放”框架的方式:

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线程来发送消息...

rust static mutable pyo3 lazy-static
1个回答
0
投票

如果没有某种内部可变性,就无法写入

OnceLock
中的值,此时您应该使用它而不是
OnceLock

也不清楚为什么您需要

Box

考虑使用

Mutex<Option<_>>
。您可以使用
Option::take
来“窃取”
Option
的内容,而留下
None

static SUSPENDED_FRAMEWORK_OPTION: Mutex<Option<HandlingFramework>> = Mutex::new(None);

// ...

if std::matches!(job_suspended_state, JobSuspendedState::Suspended) {
    let guard = SUSPENDED_FRAMEWORK_OPTION.lock().unwrap();
    *guard = handling_framework;
}

稍后你可以像这样取出值:

let mut framework = SUSPENDED_FRAMEWORK_OPTION
    .lock()
    .unwrap()
    .take()
    .unwrap();
© www.soinside.com 2019 - 2024. All rights reserved.