#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.
Комментариев нет:
Отправить комментарий