Advertisement
Guest User

Untitled

a guest
Mar 18th, 2019
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.58 KB | None | 0 0
  1. use std::mem;
  2. use std::sync::Arc;
  3. use std::sync::atomic::{Ordering, AtomicPtr};
  4.  
  5. /// Synchronized data structure which allows for lock-free reads of enclosed data.
  6. pub struct FreeReader<T> {
  7. ptr: AtomicPtr<T>,
  8. }
  9.  
  10. impl<T> FreeReader<T> {
  11. pub fn new(data: T) -> FreeReader<T> {
  12. let data = Arc::new(data);
  13. let ptr = Arc::into_raw(data);
  14. let ptr = AtomicPtr::new(ptr as *mut T);
  15.  
  16. FreeReader {
  17. ptr
  18. }
  19. }
  20.  
  21. pub fn read(&self) -> Arc<T> {
  22. let ptr = self.ptr.load(Ordering::Relaxed);
  23. let data = unsafe { Arc::from_raw(ptr as *const T) };
  24.  
  25. let ret = data.clone();
  26.  
  27. // forget the original Arc so we don't drop its reference count
  28. mem::forget(data);
  29.  
  30. ret
  31. }
  32.  
  33. pub fn store(&self, new_data: T) {
  34. let new_data = Arc::new(new_data);
  35. let new_ptr = Arc::into_raw(new_data);
  36.  
  37. let ptr = self.ptr.swap(new_ptr as *mut T, Ordering::AcqRel);
  38.  
  39. // drop the old data to drop its reference count
  40. unsafe { Arc::from_raw(ptr as *const T) };
  41. }
  42.  
  43. pub fn compare_and_store(&self, mut new_data: impl FnMut(Arc<T>) -> T) {
  44. let mut old_ptr = self.ptr.load(Ordering::Acquire);
  45.  
  46. loop {
  47. let old_data = unsafe { Arc::from_raw(old_ptr as *const T) };
  48. let data = new_data(old_data);
  49. let new_ptr = Arc::into_raw(Arc::new(data)) as *mut T;
  50.  
  51. let new_ptr = self.ptr.compare_and_swap(old_ptr, new_ptr, Ordering::AcqRel);
  52. if new_ptr == old_ptr {
  53. break;
  54. } else {
  55. old_ptr = new_ptr;
  56. }
  57. }
  58. }
  59. }
  60.  
  61. impl<T> Drop for FreeReader<T> {
  62. fn drop(&mut self) {
  63. let ptr = self.ptr.load(Ordering::SeqCst);
  64.  
  65. // drop the old data to drop its reference count
  66. unsafe { Arc::from_raw(ptr as *const T) };
  67. }
  68. }
  69.  
  70. fn main() {
  71. use std::thread;
  72. use std::sync::Barrier;
  73.  
  74. let mut threads = vec![];
  75. let data = Arc::new(FreeReader::new(5usize));
  76. let artificial_wait = Arc::new(Barrier::new(5));
  77.  
  78. for _ in 0..10 {
  79. let reader = data.clone();
  80. let artificial_wait = artificial_wait.clone();
  81. threads.push(thread::spawn(move || {
  82. artificial_wait.wait();
  83. reader.compare_and_store(|old_value| {
  84. println!("old_value: {}", *old_value);
  85. *old_value + 1
  86. });
  87. }));
  88. }
  89.  
  90. for t in threads {
  91. t.join().unwrap();
  92. }
  93. println!("\nnew value: {}", *data.read());
  94. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement