2016-08-20 2 views
1
use std::marker; 
use std::ops; 
pub struct Shared<'r, T: 'r> { 
    data: *mut T, 
    _pd: marker::PhantomData<&'r T>, 
} 

impl<'r, T> Shared<'r, T> { 
    pub fn new(value: T) -> Shared<'r, T> { 
     let boxed = Box::new(value); 
     Shared { 
      data: Box::into_raw(boxed), 
      _pd: marker::PhantomData, 
     } 
    } 

    pub fn as_ref(&self) -> SharedRef<'r, T> { 
     SharedRef { 
      data: self.data, 
      _pd: marker::PhantomData, 
     } 
    } 
} 

impl<'r, T> ops::Deref for Shared<'r, T> { 
    type Target = T; 
    fn deref(&self) -> &T { 
     unsafe { &*self.data } 
    } 
} 

pub struct SharedRef<'r, T: 'r> { 
    data: *mut T, 
    _pd: marker::PhantomData<&'r T>, 
} 

impl<'r, T> ops::Deref for SharedRef<'r, T> { 
    type Target = T; 
    fn deref(&self) -> &T { 
     unsafe { &*self.data } 
    } 
} 

impl<'r, T> Drop for Shared<'r, T> { 
    fn drop(&mut self) { 
     unsafe { 
      Box::from_raw(self.data); 
     } 
    } 
} 

fn main() { 
    let s = Shared::new(42); 
    let s_ref = s.as_ref(); 
    { 
     let s1 = s; 
    } 
    // lifetime should end here 
    println!("{}", *s_ref); 
} 

То, что я хотел выразить, было смешением между Box и Arc. Уникальный указатель, который также способен выдавать ссылки.Можно ли перемещаться даже с неизменяемыми записями?

Проблема в том, что я хочу иметь возможность перемещать Shared вокруг, даже если в нем есть неизменные данные. Это должно быть законным в этом сценарии, потому что это куча выделена.

Проблема в том, что я понятия не имею, как выразить это.

fn main() { 
    let s = Shared::new(42); 
    let s_ref = s.as_ref(); 
    { 
     let s1 = s; 
    } 
    // lifetime should end here 
    println!("{}", *s_ref); 
} 

Здесь я перехожу s в сферу с «меньшим» жизни, чем это было раньше. Но теперь, после того как я переместил s в s1, s_ref больше не должен быть доступен. Поэтому я хочу сказать, что нормально перемещать Shared, если время жизни не уменьшается.

Можно ли это выразить в ржавчине?

+0

Вы видели [владеющий-ref] (https://github.com/Kimundi/owning-ref-rs)? – Shepmaster

+0

'PhantomData' в' Shared' выглядит не так, 'Shared' * принадлежит * свой элемент. –

+0

@Shepmaster У меня нет, но я не уверен, поможет ли это мне. Я задал более конкретный вопрос: http://stackoverflow.com/questions/39079922/is-it-possible-to-have-internal-pointers-without-using-an-arc –

ответ

1

Причина Rust позволяет выйти из Shared является то, что вы не привязаны к жизни возвращенного SharedRef к нему:

pub fn as_ref(&self) -> SharedRef<'r, T> { 
    SharedRef { 
     data: self.data, 
     _pd: marker::PhantomData, 
    } 
} 

аннотирования &self фиксирует, что:

pub fn as_ref(&'r self) -> SharedRef<'r, T> { .. } 

Мое настоящее понимание заключается в том, что ключевое различие здесь заключается в том, что это говорит о том, что время жизни SharedRef теперь соответствует времени жизни заимствовать из self, сохраняя заимствование в живых. Действительно, это не должно быть одинаковое время жизни ('r), как в Shared; он работает с новым сроком службы только для займа/возврата:

pub fn as_ref<'b>(&'b self) -> SharedRef<'b, T> { .. } 

Это также запрещает движение.

Что касается бонусной части вопроса, где вы хотите разрешить перемещение, пока это что-то с достаточно продолжительным жизненным циклом, я думаю, что ответ отрицательный. Единственный способ, который я знаю, чтобы остановить что-то перемещение, - это заимствовать его, и это останавливает любой ход.

Смежные вопросы