Управление несколькими срезами одного и того же раздела памяти - PullRequest
0 голосов
/ 03 марта 2019

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

С точки зрения высокого уровня, это не очевиднодля меня, почему это не может быть сделано, так как мне не нужно перемещать или изменять исходный фрагмент.Мне нужно только несколько видов среза с тем же временем жизни, что и у исходного среза.

Чтобы проиллюстрировать это, обратитесь к этой диаграмме:

Memory Model

Исходный срез зеленого цвета, и каждый нижний слой представляет срезы все меньшего и меньшего размера, пока в срезе не окажется только один элемент.Я хочу, чтобы время жизни элементов каждого среза «доходило» до исходного среза, а не зависело от времени жизни среза над ним.Я использую эти фрагменты внутри цикла while и сохраняю каждый из фрагментов в очереди, которая длится на протяжении цикла.

Проблема, с которой я сталкиваюсь, заключается в том, что фрагменты этого не делают "жить достаточно долго ", хотя я не совсем понимаю, почему это так.

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

Вот код, который точно демонстрирует проблему:

pub struct Split<'a> {
    pub first_half: &'a [&'a [u8]],
    pub second_half: &'a [&'a [u8]],
}

impl<'a> Split<'a> {
    pub fn new(first_half: &'a [&'a [u8]], second_half: &'a [&'a [u8]]) -> Split<'a> {
        Self {
            first_half,
            second_half,
        }
    }
}

fn make_smaller_slice<'a>(slice: &'a [&'a [u8]]) -> Vec<&'a [u8]> {
    let mut smaller_slice = Vec::with_capacity(slice.len());
    for elem in slice {
        if true {
            smaller_slice.push(*elem)
        }
    }

    smaller_slice
}

fn main() {
    let mut original_data = Vec::with_capacity(100);
    for i in 0..100 {
        original_data.push(vec![i]);
    }
    let original_slice = original_data
        .iter()
        .map(|x| x.as_slice())
        .collect::<Vec<_>>();
    let mut split_queue = vec![];
    split_queue.push(Split::new(&original_slice[0..50], &original_slice[50..100]));
    loop {
        let split = split_queue.remove(0);
        let first_half = split.first_half.split_at(split.first_half.len() / 2);

        let processed_first_half_0 = make_smaller_slice(&first_half.0);
        let processed_first_half_1 = make_smaller_slice(&first_half.1);

        let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
        split_queue.insert(0, first_split);
    }
}

И возникающие ошибки:

error[E0597]: `processed_first_half_0` does not live long enough
  --> src/main.rs:44:38
   |
38 |         let split = split_queue.remove(0);
   |                     ----------- borrow used here, in later iteration of loop
...
44 |         let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
   |                                      ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
45 |         split_queue.insert(0, first_split);
46 |     }
   |     - `processed_first_half_0` dropped here while still borrowed

error[E0597]: `processed_first_half_1` does not live long enough
  --> src/main.rs:44:63
   |
38 |         let split = split_queue.remove(0);
   |                     ----------- borrow used here, in later iteration of loop
...
44 |         let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
   |                                                               ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
45 |         split_queue.insert(0, first_split);
46 |     }
   |     - `processed_first_half_1` dropped here while still borrowed

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

В вашем коде есть потенциальная проблема.В этих двух строках:

let split = split_queue.remove(0);
split_queue.insert(0, first_split);

это работает во времени, пропорциональном длине split_queue.Возможно, вы захотите заменить Vec на VecDeque и его методы постоянного времени pop_front и push_front.

0 голосов
/ 03 марта 2019

Изменение make_smaller_slice для возврата ссылки на фрагмент вместо вектора решает проблему.

pub struct Split<'a> {
    pub first_half: &'a [&'a [u8]],
    pub second_half: &'a [&'a [u8]]
}

impl<'a> Split<'a> {
    pub fn new(first_half: &'a [&'a [u8]], second_half: &'a [&'a [u8]]) -> Split<'a> {
        Self {
            first_half,
            second_half
        }
    }
}

fn make_smaller_slice<'a>(slice: &'a [&'a [u8]]) -> &'a[&'a [u8]] {
    let mut start_bound = 0;
    for i in 0..slice.len() {
        if true {
            start_bound = i;
        } 
    }

    &slice[start_bound..]
}

fn main() {
    let mut original_data = Vec::with_capacity(100);
    for i in 0..100 {
        original_data.push(vec![i]);
    }
    let original_slice = original_data.iter().map(|x| x.as_slice()).collect::<Vec<_>>();
    let mut split_queue = vec![];
    split_queue.push(Split::new(&original_slice[0..50], &original_slice[50..100]));
    loop {
        let split = split_queue.remove(0);
        let first_half = split.first_half.split_at(split.first_half.len() / 2);

        let processed_first_half_0 = make_smaller_slice(&first_half.0);
        let processed_first_half_1 = make_smaller_slice(&first_half.1);

        let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
        split_queue.insert(0, first_split);
    }
}

Кредит за _TheDust_ от Reddit для этого.

...