Created
June 29, 2017 10:54
-
-
Save pftbest/fd8782eae59a02c39c88247dd0ad5023 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
extern crate core; | |
use core::default::Default; | |
use core::sync::atomic::{AtomicUsize, Ordering}; | |
use core::cell::UnsafeCell; | |
const RING_SIZE: usize = 32; | |
pub struct Ring<T: Clone + Copy> { | |
head: AtomicUsize, | |
tail: AtomicUsize, | |
data: UnsafeCell<[T; RING_SIZE]>, | |
} | |
unsafe impl<T: Clone + Copy> Sync for Ring<T> {} | |
impl<T: Clone + Copy> Ring<T> { | |
pub fn new() -> Self | |
where | |
T: Default, | |
{ | |
Ring { | |
head: AtomicUsize::new(0), | |
tail: AtomicUsize::new(0), | |
data: UnsafeCell::new([T::default(); RING_SIZE]), | |
} | |
} | |
pub fn put(&self, data: T) -> Result<(), ()> { | |
let head = self.head.load(Ordering::Relaxed); | |
let tail = self.tail.load(Ordering::Acquire); | |
let next_head = (head + 1) % RING_SIZE; | |
if next_head == tail { | |
return Err(()); | |
} | |
unsafe { | |
(*self.data.get())[head] = data; | |
} | |
self.head.store(next_head, Ordering::Release); | |
Ok(()) | |
} | |
pub fn get(&self) -> Result<T, ()> { | |
let tail = self.tail.load(Ordering::Relaxed); | |
let head = self.head.load(Ordering::Acquire); | |
if head == tail { | |
return Err(()); | |
} | |
let data = unsafe { (*self.data.get())[tail] }; | |
let next_tail = (tail + 1) % RING_SIZE; | |
self.tail.store(next_tail, Ordering::Release); | |
Ok(data) | |
} | |
} | |
use std::thread; | |
use std::sync::Arc; | |
fn main() { | |
let a = Arc::new(Ring::<u8>::new()); | |
let b = a.clone(); | |
const N: u32 = 10000; | |
let t1 = thread::spawn(move || { | |
let mut sum: u32 = 0; | |
for i in 0..N { | |
sum += (i as u8) as u32; | |
while let Err(_) = a.put(i as u8) {} | |
} | |
println!("Sent total: {}", sum); | |
}); | |
let t2 = thread::spawn(move || { | |
let mut sum: u32 = 0; | |
for _ in 0..N { | |
let mut data = b.get(); | |
while data.is_err() { | |
data = b.get(); | |
} | |
sum += data.unwrap() as u32; | |
} | |
assert!(b.get().is_err()); | |
println!("Received total: {}", sum); | |
}); | |
t1.join().unwrap(); | |
t2.join().unwrap(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment