Guest User

Untitled

a guest
Aug 17th, 2026
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.92 KB | Software | 0 0
  1. use core::slice;
  2. use std::{
  3.     ops::{Deref, DerefMut},
  4.     sync::Arc,
  5.     thread,
  6. };
  7.  
  8. fn main() {
  9.     let v = vec![0u32; 256];
  10.     let (handle, refs) = scatter(v, 64);
  11.  
  12.     refs.into_iter()
  13.         .map(|mut r| thread::spawn(move || r.iter_mut().for_each(|v| *v += 1)))
  14.         .collect::<Vec<_>>()
  15.         .into_iter()
  16.         .for_each(|h| h.join().unwrap());
  17.  
  18.     let Ok(v) = handle.try_gather() else {
  19.         println!("fail to gather");
  20.         return;
  21.     };
  22.  
  23.     println!("v_sum = {}", v.into_iter().sum::<u32>());
  24. }
  25.  
  26. struct GatherHandle<T>(Arc<GatherHanleInner<T>>);
  27.  
  28. struct GatherHanleInner<T> {
  29.     ptr: *mut T,
  30.     length: usize,
  31.     capacity: usize,
  32.     alive: bool,
  33. }
  34. impl<T> GatherHandle<T> {
  35.     fn try_gather(self) -> Result<Vec<T>, Self> {
  36.         let mut inner = match Arc::try_unwrap(self.0) {
  37.             Ok(v) => v,
  38.             Err(v) => return Err(Self(v)),
  39.         };
  40.  
  41.         // Safety:
  42.         // disarming check in Drop
  43.         inner.alive = false;
  44.         // Safety:
  45.         // Ok because each ScatteredRef<T> has GatherHandle<T>,
  46.         // so if we have GatherHandleInner<T> there are no ScatteredRef<T>'s left
  47.         Ok(unsafe { Vec::from_raw_parts(inner.ptr, inner.length, inner.capacity) })
  48.     }
  49. }
  50. impl<T> Drop for GatherHanleInner<T> {
  51.     fn drop(&mut self) {
  52.         if self.alive {
  53.             drop(unsafe { Vec::from_raw_parts(self.ptr, self.length, self.capacity) });
  54.         }
  55.     }
  56. }
  57. struct ScatteredRef<T> {
  58.     ptr: *mut T,
  59.     length: usize,
  60.  
  61.     _h: GatherHandle<T>,
  62. }
  63. // Safety: Ok because Arc::unwrap() and Arc::drop() do aquire/release semantics
  64. unsafe impl<T: Send> Send for ScatteredRef<T> {}
  65.  
  66. impl<T> Deref for ScatteredRef<T> {
  67.     type Target = [T];
  68.     fn deref(&self) -> &Self::Target {
  69.         // Safety: Ok because Self<T> is basically &mut[T] for current chunk
  70.         unsafe { slice::from_raw_parts(self.ptr, self.length) }
  71.     }
  72. }
  73. impl<T> DerefMut for ScatteredRef<T> {
  74.     fn deref_mut(&mut self) -> &mut Self::Target {
  75.         // Safety: See Self::deref()
  76.         unsafe { slice::from_raw_parts_mut(self.ptr, self.length) }
  77.     }
  78. }
  79.  
  80. /// Scatter Vec<T> into `count` size owned mutable slices
  81. /// and gather it back after all slices (ScatterRef<T>) are dropped
  82. fn scatter<T>(v: Vec<T>, count: usize) -> (GatherHandle<T>, Vec<ScatteredRef<T>>) {
  83.     assert!(v.len() > count);
  84.     assert!(v.len() % count == 0);
  85.  
  86.     let refs_count = v.len() / count;
  87.  
  88.     let (ptr, length, capacity) = Vec::into_raw_parts(v);
  89.     let handle = GatherHandle(Arc::new(GatherHanleInner {
  90.         ptr,
  91.         length,
  92.         capacity,
  93.         alive: true,
  94.     }));
  95.  
  96.     let refs = (0..refs_count)
  97.         .into_iter()
  98.         .map(|id| unsafe {
  99.             ScatteredRef {
  100.                 ptr: ptr.add(count * id),
  101.                 length: count,
  102.                 _h: GatherHandle(Arc::clone(&handle.0)),
  103.             }
  104.         })
  105.         .collect();
  106.  
  107.     (handle, refs)
  108. }
  109.  
  110. #[cfg(test)]
  111. mod tests {
  112.     use super::*;
  113.  
  114.     #[test]
  115.     fn error_when_refs_are_alive() {
  116.         let v = vec![0u32; 256];
  117.         let (handle, refs) = scatter(v, 64);
  118.  
  119.         assert!(handle.try_gather().is_err());
  120.         drop(refs);
  121.     }
  122.     #[test]
  123.     fn ok_when_refs_are_dead() {
  124.         let v = vec![0u32; 256];
  125.         let (handle, refs) = scatter(v, 64);
  126.  
  127.         drop(refs);
  128.         assert!(handle.try_gather().is_ok());
  129.     }
  130.  
  131.     #[test]
  132.     fn error_when_single_ref_is_alive() {
  133.         let v = vec![0u32; 256];
  134.         let (handle, mut refs) = scatter(v, 64);
  135.  
  136.         let first = refs.remove(0);
  137.         drop(refs);
  138.  
  139.         assert!(handle.try_gather().is_err());
  140.         drop(first);
  141.     }
  142.     #[test]
  143.     fn miri_ok_when_dropping_nahdle_but_refs_are_alive() {
  144.         let v = vec![0u32; 256];
  145.         let (handle, mut refs) = scatter(v, 64);
  146.  
  147.         drop(handle);
  148.         let _first = refs.remove(0);
  149.         drop(refs);
  150.     }
  151. }
Advertisement
Add Comment
Please, Sign In to add comment