#rust #mutex
Читаю Rustbook и не понимаю некоторые вещи. use std::sync::{Arc, Mutex}; use std::thread; fn main() { let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); for i in 0..3 { let data = data.clone(); //(1) thread::spawn(move || { let mut data = data.lock().unwrap(); //(2) data[i] += 1; }); } thread::sleep_ms(50); } (1). Метод clone() возвращает тип self, т.е. Arc<_>. В этом можно убедиться, если явно написать тип: let data: Arc>> = data.clone(); В связи с этим возникает вопрос: почему в (2) мы вызываем метод lock() так, если бы мы работали напрямую с Mutex? Все как в C++, но там у shared_ptr оператор -> перегружен за нас, а покопавшись в исходниках arc.rs я не увидел подобного или пропустил. UPD Спасибо Кнопкатык за наводку на Deref coercions. Для закрепления написал такой искусственный пример: use std::ops::Deref; #[derive(Debug)] struct Field { x: i32, } impl Field{ fn print(&self){ println!("x = {}", self.x); } } #[derive(Debug)] struct Example { x: Field, } impl Deref for Example{ type Target = Field; fn deref(&self) -> &Field{ &self.x } } fn main() { let s = Example { x: Field { x: 5} }; s.print(); } Структура Example не имеет имплементации метода print. Но если вспомнить универсальный синтаксис вызова функций, то s.print(); можно заменить на: Field::print(&s); Следовательно, так как у нас есть реализация типажа Deref для Example, возвращающая &Field, то значения Example, если нужно, будут автоматически преобразовываться в &Field при разыменовании: Field::print(&Example) -> dereference -> Field::print(&Field); Код, как и предполагается, выведет: x = 5
Ответы
Ответ 1
Дело в механизме Deref coercions или "Преобразования при разыменовании". Arc реализует типаж Deref, значения &Arcбудут автоматически преобразованы в &T, когда это необходимо. Метод lock(&self) Мютекса принимает &self, и когда мы пытаемся вызвать его с Arc: lock(&Arc ) срабатывает механизм Deref coercions lock(&Mutex) а &Mutex это и есть &self для метода lock.
Комментариев нет:
Отправить комментарий