Advertisement
Guest User

Untitled

a guest
Jun 29th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.15 KB | None | 0 0
  1. extern crate core;
  2.  
  3. use core::default::Default;
  4. use core::sync::atomic::{AtomicUsize, Ordering};
  5. use core::cell::UnsafeCell;
  6.  
  7. const RING_SIZE: usize = 32;
  8.  
  9. pub struct Ring<T: Clone + Copy> {
  10. head: AtomicUsize,
  11. tail: AtomicUsize,
  12. data: UnsafeCell<[T; RING_SIZE]>,
  13. }
  14.  
  15. unsafe impl<T: Clone + Copy> Sync for Ring<T> {}
  16.  
  17. impl<T: Clone + Copy> Ring<T> {
  18. pub fn new() -> Self
  19. where
  20. T: Default,
  21. {
  22. Ring {
  23. head: AtomicUsize::new(0),
  24. tail: AtomicUsize::new(0),
  25. data: UnsafeCell::new([T::default(); RING_SIZE]),
  26. }
  27. }
  28.  
  29. pub fn put(&self, data: T) -> Result<(), ()> {
  30. let head = self.head.load(Ordering::Relaxed);
  31. let tail = self.tail.load(Ordering::Acquire);
  32.  
  33. let next_head = (head + 1) % RING_SIZE;
  34. if next_head == tail {
  35. return Err(());
  36. }
  37.  
  38. unsafe {
  39. (*self.data.get())[head] = data;
  40. }
  41.  
  42. self.head.store(next_head, Ordering::Release);
  43. Ok(())
  44. }
  45.  
  46. pub fn get(&self) -> Result<T, ()> {
  47. let tail = self.tail.load(Ordering::Relaxed);
  48. let head = self.head.load(Ordering::Acquire);
  49.  
  50. if head == tail {
  51. return Err(());
  52. }
  53.  
  54. let data = unsafe { (*self.data.get())[tail] };
  55.  
  56. let next_tail = (tail + 1) % RING_SIZE;
  57. self.tail.store(next_tail, Ordering::Release);
  58. Ok(data)
  59. }
  60. }
  61.  
  62. use std::thread;
  63. use std::sync::Arc;
  64.  
  65. fn main() {
  66. let a = Arc::new(Ring::<u8>::new());
  67. let b = a.clone();
  68.  
  69. const N: u32 = 10000;
  70.  
  71. let t1 = thread::spawn(move || {
  72. let mut sum: u32 = 0;
  73. for i in 0..N {
  74. sum += (i as u8) as u32;
  75. while let Err(_) = a.put(i as u8) {}
  76. }
  77. println!("Sent total: {}", sum);
  78. });
  79.  
  80. let t2 = thread::spawn(move || {
  81. let mut sum: u32 = 0;
  82. for _ in 0..N {
  83. let mut data = b.get();
  84. while data.is_err() {
  85. data = b.get();
  86. }
  87. sum += data.unwrap() as u32;
  88. }
  89. assert!(b.get().is_err());
  90. println!("Received total: {}", sum);
  91. });
  92.  
  93. t1.join().unwrap();
  94. t2.join().unwrap();
  95. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement