Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 这种保护单个资源在Rust中使用的无锁结构是否正确?_Multithreading_Rust_Lock Free - Fatal编程技术网

Multithreading 这种保护单个资源在Rust中使用的无锁结构是否正确?

Multithreading 这种保护单个资源在Rust中使用的无锁结构是否正确?,multithreading,rust,lock-free,Multithreading,Rust,Lock Free,我正在尝试创建一个可以通过多个线程封送资源使用的结构。我相信我已经找到了一个正确的实现,但我仍然在学习内存顺序等,所以我想确保我的推理是正确的 资源单元有三个操作(除创建外): try\u acquire,它尝试获取对资源的可变引用 try\u take,它尝试取出资源,使单元格为空 try_reserve,它在空单元格中为线程保留空间以放置新资源 为了实现这一点,我创建了一个包含UnsafeCell的结构,其中包含三种可能的状态 const EMPTY: usize = 0; const

我正在尝试创建一个可以通过多个线程封送资源使用的结构。我相信我已经找到了一个正确的实现,但我仍然在学习内存顺序等,所以我想确保我的推理是正确的

资源单元有三个操作(除创建外):

  • try\u acquire
    ,它尝试获取对资源的可变引用
  • try\u take
    ,它尝试取出资源,使单元格为空
  • try_reserve
    ,它在空单元格中为线程保留空间以放置新资源
为了实现这一点,我创建了一个包含
UnsafeCell
的结构,其中包含三种可能的状态

const EMPTY: usize = 0;
const FULL: usize = 1;
const IN_USE: usize = 2;

pub struct ResourceCell<T: Send> {
    status: AtomicUsize,
    resource: UnsafeCell<Option<T>>,
}

我对rust了解不够,无法对代码进行评论,但可能也能提供帮助?我认为
ResourceCell
本质上等同于
Mutex
?@trentcl是的,本质上是一样的,只是你不必锁定它来判断它是否为空。
pub fn try_acquire(&self) -> Result<Guard<T>, ()> {
    if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
        // A Guard allows mutable access to the resource for its lifetime
        // then when dropped, it calls status.store(FULL, Ordering::Release);
        return Ok(Guard(self))
    }
    Err(())
}

pub fn try_take(&self) -> Result<T, ()> {
    if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
        let value = self.resource.get().take().unwrap();
        self.cell.status.store(EMPTY, Ordering::Release);
        return Ok(value);
    }
    Err(())
}

pub fn try_reserve(&self) -> Result<Reserve<T>, ()> {
    if self.status.compare_and_swap(EMPTY, IN_USE, Ordering::Acquire) == IN_USE {
        // A Reserve has a single method that consumes itself and places a new 
        // value in the resource cell, then calls status.store(FULL, Ordering::Release);
        return Ok(Reserve(self))
    }
    Err(())
}
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::cell::UnsafeCell;

const EMPTY: usize = 0;
const FULL: usize = 1;
const IN_USE: usize = 2;

pub struct ResourceCell<T: Send> {
    status: AtomicUsize,
    resource: UnsafeCell<Option<T>>,
}

impl<T: Send> ResourceCell<T> {
    pub fn new(data: Option<T>) -> ResourceCell<T> {
        ResourceCell {
            status: AtomicUsize::new(if data.is_none() { EMPTY } else { FULL }),
            resource: UnsafeCell::new(data)
        }
    }

    pub fn try_acquire(&self) -> Result<Guard<T>, ()> {
        if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
            return Ok(Guard(self, FULL)) 
        }
        Err(())
    }

    pub fn try_take(&self) -> Result<T, ()> {
        if self.status.compare_and_swap(FULL, IN_USE, Ordering::Acquire) == IN_USE {
            let value = unsafe { self.resource.get().as_mut().unwrap().take().unwrap() };
            self.status.store(EMPTY, Ordering::Release);
            return Ok(value);
        }
        Err(())
    }

    pub fn try_reserve(&self) -> Result<Reserve<T>, ()> {
        if self.status.compare_and_swap(EMPTY, IN_USE, Ordering::Acquire) == IN_USE {
            return Ok(Reserve(self))
        }
        Err(())
    }
}

unsafe impl<T: Send> Sync for ResourceCell<T> { }

pub struct Guard<'a, T: Send + 'a>(&'a ResourceCell<T>, usize);

impl<'a, T: Send + 'a> Guard<'a, T> {
    pub fn take(mut self) -> T {
        let value = unsafe { self.0.resource.get().as_mut().unwrap().take().unwrap() };
        self.1 = EMPTY;
        return value;
    }
}

impl<'a, T: Send + 'a> Drop for Guard<'a, T> {
    fn drop(&mut self) {
        self.0.status.store(self.1, Ordering::Release);
    }
}

impl<'a, T: Send + 'a> Deref for Guard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        return unsafe { self.0.resource.get().as_ref().unwrap().as_ref().unwrap() };
    }
}

impl<'a, T: Send + 'a> DerefMut for Guard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        return unsafe { self.0.resource.get().as_mut().unwrap().as_mut().unwrap() };
    }
}

pub struct Reserve<'a, T: Send + 'a>(&'a ResourceCell<T>); 

impl<'a, T: Send + 'a> Reserve<'a, T> {
    pub fn fill(self, value: T) {
        unsafe { *self.0.resource.get().as_mut().unwrap() = Some(value) };
        self.0.status.store(FULL, Ordering::Release);
    }
}