Issues moving data from one Vec to another

I'm trying to make a RoundRobin process simulation program, and I'm having issues. I first try to get the arrival times == 0, then I place the rest in a VecDeque 'unused'. I can't figure out how to check each loop it removes a duration tick if something from unused should be part of the main workload, and to swap between VecDeques. Here's some code, I couldn't figure out how to make a simpler working sample:

pub struct Process {
    pub arrival: i32,
    pub first_run: Option<i32>,
    pub duration: i32,
    pub completion: Option<i32>,
}

pub struct ArrivalQueue {
    pub arrival: i32,
    pub duration: i32,
    pub process: Option<Process>,
}

// -- snip -- 

let mut wl = VecDeque::new();
let mut unused = VecDeque::new();

// This has no problems
for w in workload { // workload: Vec<ArrivalQueue>
   if w.arrival >= 0 {
        wl.push_front(w.clone());
    } else { 
        unused.push_front(w.clone()) 
    }
}

let mut runtime = 0;

while !wl.is_empty() {
   // Getting front and modifying it
   let mut queue: ArrivalQueue = wl.pop_front().unwrap(); // issue if runtime < first_arrival
   let p: &mut Process = queue.process.as_mut().unwrap();
   
    // -- snip --

    // Adds elements if time allows
    // THIS doesn't work. I don't know a good way to swap between the VecDeques
    for w in unused { // unused: VecDeque<ArrivalQueue>
        if w.arrival >= 0 {
            wl.push_front(w);
            unused.pop_front();
        } else { break; }
    }
}

To pop elements from the front of unused and push them onto the front of wl as long as each element has .arrival >= 0, you can do:

while unused.front().is_some_and(|w| w.arrival >= 0) {
    wl.push_front(unused.pop_front().unwrap());
}

I don't like that unwrap(), but at the moment I can't think of a decent way to avoid it.

2 Likes

Thank you!

You can write it without unwrap:

while let Some(w) = unused.pop_front().filter(|w| w.arrival >= 0) {
    wl.push_front(w)
}

This will pop one extra item, so not exactly equivalent.

3 Likes

Right, thanks. Would need an entry-style API for that.

Another way to write this is to find the split point first, then drain that range into the other, something like this:

let arrived = unused.iter().position(|w| w.arrival < 0).unwrap_or(unused.len());
wl.extend(unused.drain(..arrived));

It will probably end up compiling to very similar code, so it's mostly a preference thing.


Also, nit:

You can simplify this as:

while let Some(mut queue) = wl.pop_front() {

I think clippy will tell you about this one? (cargo clippy)

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.