Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement