Created
January 21, 2023 21:33
-
-
Save rawnly/2619f40f90d203a071036bdb211c152f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- data: VecDeque<T> | |
+ data: Mutex<VecDeque<T>> | |
+ cv: CondVar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- fn pop(&self) -> Option<T>; | |
+ fn pop(&self) -> T; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///! queue/mod.rs | |
use std::collections::VecDeque; | |
/// A FIFO queue implemented using a VecDeque | |
struct FifoQueue<T> { | |
/// The underlying data structure of the queue | |
data: VecDeque<T> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///! queue/mod.rs | |
use std::{ thread, sync::Arc, time::Duration }; | |
#[cfg(test)] | |
mod test { | |
use crate::queue::prelude::*; | |
use crate::queue::FifoQueue; | |
use std::{sync::Arc, thread}; | |
#[test] | |
fn test_queue_thread_safety() { | |
// create a queue of numbers | |
let queue = Arc::new(FifoQueue::<i32>::new()); | |
let q1 = queue.clone(); | |
let t1 = thread::spawn(move || { | |
q1.push(1); | |
q1.push(2); | |
}); | |
let q2 = queue.clone(); | |
let t2 = thread::spawn(move || { | |
q2.push(3); | |
q2.push(4) | |
}); | |
t1.join().unwrap(); | |
t2.join().unwrap(); | |
assert_eq!(queue.len(), 4); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///! queue/mod.rs | |
use std::{ collections::VecDeque, sync::{Mutex, CondVar} }; | |
/// includes common traits | |
pub mod prelude; | |
// import our Queue<T> trait | |
use self::prelude::*; | |
struct FifoQueue<T> { | |
data: Mutex<VecDeque<T>>, | |
/// The condvar used to signal when the queue is not empty | |
cv: CondVar | |
} | |
impl<T> Queue<T> for FifoQueue<T> { | |
fn new() -> Self { | |
Self { | |
data: Mutex::new(VecDeque::new()), | |
cv: CondVar::new() | |
} | |
} | |
/// push input on the back of the queue | |
/// - unrecoverable if lock fails so just unwrap | |
fn push(&self, value: T) { | |
let mut data = self.data.lock().unwrap(); | |
data.push_back(value) | |
// notify the thread that the queue has been populated | |
self.cv.notify_one(); | |
} | |
/// pop element from the queue | |
/// - unrecoverable if the lock fails so just unwrap | |
/// - same for condvar variable | |
fn pop(&self) -> T { | |
let mut data = self.data.lock().unwrap(); | |
// wait for the notification if the queue is empty | |
while data.is_empty() { | |
data = self.cv.wait(data).unwrap(); | |
} | |
data.pop_front().unwrap() | |
} | |
fn len(&self) -> usize { | |
let data = self.data.lock().unwrap(); | |
data.len() | |
} | |
fn is_empty(&self) -> bool { | |
let data = self.data.lock().unwrap(); | |
data.is_empty() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///! queue/prelude.rs | |
impl<T> Queue<T> for FifoQueue<T> { | |
fn new() -> Self { | |
Self { | |
data: VecDeque::new() | |
} | |
} | |
/// Adds an element to the back of the queue | |
fn push(&self, value: T) { | |
self.data.push_back(value) | |
} | |
/// Removes an element from the front of the queue | |
fn pop(&self) -> Option<T> { | |
self.data.pop_front() | |
} | |
fn len(&self) -> usize { | |
self.data.len() | |
} | |
fn is_empty(&self) -> bool { | |
self.data.is_empty() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Queue<T> { | |
/// Creates a new, empty queue | |
fn new() -> Self; | |
/// Enqueue a new value | |
fn push(&self, value: T); | |
/// Dequeue a value | |
/// Returns None if the queue is empty | |
fn pop(&self) -> Option<T>; | |
/// Returns the number of elements enqueued | |
fn len(&self) -> usize; | |
/// Checks if the `size()` is 0 | |
fn is_empty(&self) -> bool; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment