Какой правильный умный указатель имеет несколько сильных ссылок и допускает изменчивость?
Я хочу иметь структуру в куче с двумя ссылками; один для меня, а другой от закрытия. Обратите внимание, что код предназначен для однопоточного регистра:
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
, но слабые ссылки должны предотвратить падение. Я могу иметь две слабые ссылки и обновить их до сильных, когда мне нужна изменчивость.
Поскольку это однопоточная программа, я буду иметь только сильные ссылки за раз, поэтому все будет работать, как и ожидалось.