Я хочу иметь структуру в куче с двумя ссылками; один для меня, а другой - от закрытия. Обратите внимание, что код предназначен для однопоточного случая:
use std::rc::Rc;
#[derive(Debug)]
struct Foo {
val: u32,
}
impl Foo {
fn set_val(&mut self, val: u32) {
self.val = val;
}
}
impl Drop for Foo {
fn drop(&mut self) {
println!("we drop {:?}", self);
}
}
fn need_callback(mut cb: Box<FnMut(u32)>) {
cb(17);
}
fn create() -> Rc<Foo> {
let rc = Rc::new(Foo { val: 5 });
let weak_rc = Rc::downgrade(&rc);
need_callback(Box::new(move |x| {
if let Some(mut rc) = weak_rc.upgrade() {
if let Some(foo) = Rc::get_mut(&mut rc) {
foo.set_val(x);
}
}
}));
rc
}
fn main() {
create();
}
В реальном коде need_callback
сохраняет обратный вызов в какое-то место, но перед этим может вызвать cb
, как это делает need_callback
.
Код показывает, что std::rc::Rc
не подходит для этой задачи, потому что foo.set_val(x)
никогда не вызывается; У меня есть две сильные ссылки, и Rc::get_mut
дает None
в этом случае.
Какой умный указатель с подсчетом ссылок я должен использовать вместо std::rc::Rc
, чтобы можно было вызвать foo.set_val
? Может быть, можно исправить мой код и по-прежнему использовать std::rc::Rc
?
Поразмыслив, мне нужно что-то вроде std::rc::Rc
, но слабые ссылки должны предотвратить падение. Я могу иметь две слабые ссылки и обновлять их до сильных, когда мне нужна изменчивость.
Поскольку это однопоточная программа, у меня будут только сильные ссылки за раз, поэтому все будет работать так, как ожидалось.