use crate::drain::Drain;
use crate::queue::Queue;
use std::fmt;
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
pub struct SyncQueue<T> {
inner: Arc<RwLock<Queue<T>>>,
}
impl<T> fmt::Display for SyncQueue<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[sync] {}", self.inner.read().unwrap())
}
}
impl<T> From<Queue<T>> for SyncQueue<T> {
fn from(queue: Queue<T>) -> SyncQueue<T> {
SyncQueue {
inner: Arc::new(RwLock::new(queue)),
}
}
}
impl<T> From<SyncQueue<T>> for Queue<T>
where
T: Clone,
{
fn from(queue: SyncQueue<T>) -> Queue<T> {
queue.inner.read().unwrap().clone()
}
}
impl<T> SyncQueue<T> {
pub fn new(capacity: usize) -> Self {
SyncQueue::from(Queue::new(capacity))
}
#[inline]
pub fn len(&self) -> usize {
self.inner.read().unwrap().len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.read().unwrap().capacity()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.read().unwrap().is_empty()
}
#[inline]
pub fn is_full(&self) -> bool {
self.inner.read().unwrap().is_full()
}
#[inline]
pub fn clear(&self) {
self.inner.write().unwrap().clear()
}
pub fn resize(&self, capacity: usize) -> usize {
self.inner.write().unwrap().resize(capacity)
}
#[inline]
pub fn push(&self, item: T) -> Option<T> {
self.inner.write().unwrap().push(item)
}
#[inline]
pub fn pop(&self) -> Option<T> {
self.inner.write().unwrap().pop()
}
pub fn drain(&self) -> Drain<T> {
self.inner.write().unwrap().drain()
}
}
impl<T> SyncQueue<T>
where
T: Clone,
{
#[inline]
pub fn peek(&self) -> Option<T> {
match self.inner.read().unwrap().peek() {
Some(item) => Some(item.clone()),
None => None,
}
}
}
impl<T> FromIterator<T> for SyncQueue<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let queue = SyncQueue::new(0);
for i in iter {
queue.resize(queue.len() + 1);
queue.push(i);
}
queue
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand::Rng;
use std::thread;
#[test]
fn test_queue_0() {
let queue: SyncQueue<usize> = SyncQueue::new(0);
assert_eq!(None, queue.push(42));
assert_eq!(None, queue.pop());
assert_eq!(0, queue.capacity());
assert_eq!(true, queue.is_full());
assert_eq!(true, queue.is_empty());
}
fn monkey_fn(queue: SyncQueue<usize>) {
let mut rng = rand::thread_rng();
for i in 0..1_000_000 {
if i % 1000 == 0 {
print!(".");
}
if i % 100_000 == 0 {
queue.clear();
continue;
}
let dice = rng.gen_range(0..=100);
if dice < 50 {
queue.push(i & 100);
continue;
}
if dice < 80 {
queue.pop();
continue;
}
if dice < 90 {
queue.peek();
continue;
}
}
}
#[test]
fn test_monkey() {
let queue: SyncQueue<usize> = SyncQueue::new(50);
let queue1 = queue.clone();
let handle1 = thread::spawn(move || monkey_fn(queue1));
let queue2 = queue.clone();
let handle2 = thread::spawn(move || monkey_fn(queue2));
handle1.join().unwrap();
handle2.join().unwrap();
}
}