Читаю 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
В связи с этим возникает вопрос: почему в (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
Ответ
Дело в механизме Deref coercions или "Преобразования при разыменовании".
Arc реализует типаж Deref, значения &Arc
lock(&Arc
срабатывает механизм Deref coercions
lock(&Mutex)
а &Mutex это и есть &self для метода lock.
Комментариев нет:
Отправить комментарий