Страницы

Поиск по вопросам

четверг, 30 мая 2019 г.

Rust. Вызов метода у Arc

Читаю 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


Ответ

Дело в механизме Deref coercions или "Преобразования при разыменовании". Arc реализует типаж Deref, значения &Arc будут автоматически преобразованы в &T, когда это необходимо. Метод lock(&self) Мютекса принимает &self, и когда мы пытаемся вызвать его с Arc
lock(&Arc)
срабатывает механизм Deref coercions
lock(&Mutex)
а &Mutex это и есть &self для метода lock.

Комментариев нет:

Отправить комментарий