Время жизни Rust - возвращаемое значение из вектора в RWLock в Arc

У меня много проблем с временем жизни в отношении Arcs и RWLocks.

struct ComponentContainer<T>{
    id_to_component: HashMap<uint, uint>,
    components: Arc<RWLock<~Vec<T>>>
}

id_to_component - это отображение идентификаторов компонентов на индекс в Vec внутри компонентов.

Перепробовал все из интуитивного:

impl<T: Component> ComponentContainer<T>{
    fn get<'a>(&'a self, id: uint) -> &'a T {
        let idx = self.id_to_component.get(&id);
        self.components.read().get(*idx)
    }
}

До предельно подробного (ручное сохранение каждой ссылки):

impl<T: Component> ComponentContainer<T> {
    fn get<'a>(&'a self, id: uint) -> &'a T {
        let idx = self.id_to_component.get(&id);
        let components: &'a RWLock<~Vec<T>> = &'a *self.components;
        let c: &'a RWLock<~Vec<T>> = &'a *components;
        let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
        let v: &'a ~Vec<T> = &'a **tmp;
        v.get(*idx)
    }
}

С подробным сообщением я получаю сообщение об ошибке:

error: borrowed value does not live long enough
let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
                                            ^~~~~~~~~~~~

Согласно источнику для RWLock.read (), возвращаемая ссылка должна иметь указанное время жизни, если я не читаю ее неправильно.

Изменить: полный вывод rustc для короткой версии

test.rs:18:9: 18:31 error: borrowed value does not live long enough
test.rs:18         self.components.read().get(*idx)
                   ^~~~~~~~~~~~~~~~~~~~~~
test.rs:16:45: 19:6 note: reference must be valid for the lifetime &'a  as defined on the block at 16:44...
test.rs:16     fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17         let idx = self.id_to_component.get(&id);
test.rs:18         self.components.read().get(*idx)
test.rs:19     }
test.rs:16:45: 19:6 note: ...but borrowed value is only valid for the block at 16:44
test.rs:16     fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17         let idx = self.id_to_component.get(&id);
test.rs:18         self.components.read().get(*idx)
test.rs:19     }
error: aborting due to previous error

person compmstr    schedule 27.03.2014    source источник
comment
Скорее всего, не связаны, но почему ~Vec<T>? Насколько мне известно, Vec<T> должен работать нормально.   -  person    schedule 27.03.2014
comment
В тот момент я просто пробовал что-нибудь, черт возьми. Забыл, что это было там   -  person compmstr    schedule 27.03.2014
comment
с c.read () вы просто берете ссылку на значение и отбрасываете значение, это то, что вам сообщает colpiler   -  person Arjan    schedule 27.03.2014
comment
afaik, .read () - это способ доступа к значению в RWLock. Как мне его изменить, чтобы ценность не выбрасывалась?   -  person compmstr    schedule 27.03.2014


Ответы (1)


Давайте посмотрим на подпись _1 _ :

fn read<'a>(&'a self) -> RWLockReadGuard<'a>

Он возвращает RWLockReadGuard<'a>. Это не ссылка на RWLockReadGuard, это RWLockReadGuard, содержащая внутри ссылки времени жизни 'a.

Теперь ваша строка:

let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();

Вы берете ссылку на RWLockReadGuard. Это означает, что указанный объект должен существовать как минимум столько же, сколько и ссылка. Но это не так: значение - это значение, возвращаемое c.read(), которое нигде не сохраняется. Поскольку он нигде не хранится, он отбрасывается в конце оператора, и поэтому заимствование недействительно, потому что требуемый 'a длиннее, чем оператор, и поэтому не может быть удовлетворен.

Вместо этого вам следует просто отбросить часть &'a, используя объект напрямую:

let tmp: RWLockReadGuard<'a, ~Vec<T>> = c.read();

На первый взгляд я не уверен, что не так с вашей короткой версией, и у меня под рукой нет rustc. Выложите, пожалуйста, полную версию rustc stderr.

person Chris Morgan    schedule 28.03.2014
comment
Похоже, моя основная проблема в том, что RWLockReadGuard не имеет времени жизни, и поэтому, когда я пытаюсь вернуть значение изнутри, rustc жалуется на то, что блокировка выходит за пределы области действия до передачи данных. Итак, я предполагаю, что главный вопрос на данном этапе будет заключаться в том, как заставить RWLockReadGuard иметь соответствующее время жизни. - person compmstr; 28.03.2014