У меня есть две структуры Node
и Communicator
. Node
содержит «бизнес-логику», а Communicator
содержит методы для отправки и получения UDP-сообщений. Node
должен вызывать методы на Communicator
, когда он хочет отправлять сообщения, а Communicator
должен вызывать методы на Node
, когда он получает UDP-сообщение. Если они имеют одинаковую структуру, проблем нет вообще. Но я хочу отделить их, потому что у них явно разные обязанности. Наличие всего этого в одной структуре стало бы неуправляемым. Мой код выглядит следующим образом:
fn main() {
use std::sync::{Arc, Mutex, Condvar, Weak};
use std::thread;
pub struct Node {
communicator: Option<Arc<Communicator>>
}
impl Node {
pub fn new() -> Node {
Node {
communicator: None
}
}
pub fn set_communicator(&mut self, communicator: Arc<Communicator>) {
self.communicator = Some(communicator);
}
}
pub struct Communicator {
node: Option<Weak<Node>>
}
impl Communicator {
pub fn new() -> Communicator {
Communicator {
node: None
}
}
pub fn set_node(&mut self, node: Weak<Node>) {
self.node = Some(node);
}
}
let mut my_node = Arc::new(Node::new());
let mut my_communicator = Arc::new(Communicator::new());
Arc::get_mut(&mut my_node).unwrap().set_communicator(Arc::clone(&my_communicator));
//Arc::get_mut(&mut my_communicator).unwrap().set_node(Arc::downgrade(&my_node));
}
Мой код падает, как я и предсказывал, если я раскомментирую обе последние строки. Но это то, чего я хочу достичь.
Я вижу пару вариантов:
- Используйте
Mutex
или RwLock
, чтобы получить внутреннюю изменчивость. Но это дает снижение производительности.
- Используйте
Cell
или RefCell
. Но они не поточнобезопасны.
- Используйте
AtomicCell
из crossbeam
. Похоже, лучший вариант до сих пор. Но как насчет производительности?
- Используйте
unsafe
. Но где? И как сделать так, чтобы код оставался безопасным для памяти, несмотря на unsafe
?
Теоретически я мог бы разбить Communicator
на Sender
и Receiver
, чтобы не было циклических ссылок. Но для моей программы я знаю, что в будущем у меня будет похожая ситуация, когда это будет невозможно.
Похоже, что поскольку я просто разбил структуру на две, по причинам структурирования кода и не получая новых функциональных возможностей, должен быть способ сделать это без необходимости платить какие-либо потери производительности, как Mutex
. 1040 *