#已废弃 #列表 #future #lock #intrusive #async #pin

已废弃 无 std wait-list

为了 pin-list 而废弃

2 个版本

0.1.1 2022 年 6 月 2 日
0.1.0 2022 年 5 月 10 日

15 in #intrusive

MIT 许可证

57KB
918

wait-list

此 crate 已被废弃,推荐使用 pin-list!如果您需要其他 crate 名称,请随时 联系我 或发送电子邮件至 [email protected]

以下为原始的说明文件

此 crate 提供了 WaitList,这是异步同步中最基本的数据类型。《code>WaitList 被实现为一个 futures 的侵入式链表。

特性标志

  • std:在标准库中的锁上实现 Lock 特性。
  • lock_api_04:在 lock_api v0.4 中的锁上实现 Lock 特性。这使您能够集成 parking_lotspinusync 等crate。
  • loom_05:在 loom v0.5 中的锁上实现 Lock 特性。

示例

一个线程安全的非公平异步互斥锁。

use pin_project_lite::pin_project;
use std::cell::UnsafeCell;
use std::future::Future;
use std::ops::Deref;
use std::ops::DerefMut;
use std::pin::Pin;
use std::task;
use std::task::Poll;
use wait_list::WaitList;

pub struct Mutex<T> {
    data: UnsafeCell<T>,
    waiters: WaitList<std::sync::Mutex<bool>, (), ()>,
}

unsafe impl<T> Sync for Mutex<T> {}

impl<T> Mutex<T> {
    pub fn new(data: T) -> Self {
        Self {
            data: UnsafeCell::new(data),
            waiters: WaitList::new(std::sync::Mutex::new(false)),
        }
    }
    pub fn lock(&self) -> Lock<'_, T> {
        Lock {
            mutex: self,
            inner: wait_list::Wait::new(),
        }
    }
}

pin_project! {
    pub struct Lock<'mutex, T> {
        mutex: &'mutex Mutex<T>,
        #[pin]
        inner: wait_list::Wait<'mutex, std::sync::Mutex<bool>, (), (), TryForward>,
    }
}

impl<'mutex, T> Future for Lock<'mutex, T> {
    type Output = Guard<'mutex, T>;
    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        let mut this = self.project();

        let mut waiters = if this.inner.as_ref().is_completed() {
            // If we haven't initialized the future yet, lock the mutex for the first time
            this.mutex.waiters.lock_exclusive()
        } else {
            // Otherwise, wait for us to be woken
            match this.inner.as_mut().poll(cx) {
                Poll::Ready((waiters, ())) => waiters,
                Poll::Pending => return Poll::Pending,
            }
        };

        // If the mutex is unlocked, mark it as locked and return the guard
        if !*waiters.guard {
            *waiters.guard = true;
            return Poll::Ready(Guard { mutex: this.mutex });
        }

        // Otherwise, re-register ourselves to be woken when the mutex is unlocked again
        this.inner.init(cx.waker().clone(), &mut waiters, (), TryForward);
        Poll::Pending
    }
}

/// When the future is cancelled before the mutex guard can be taken, wake up the next waiter.
struct TryForward;
impl<'wait_list> wait_list::CancelCallback<'wait_list, std::sync::Mutex<bool>, (), ()>
    for TryForward
{
    fn on_cancel(
        self,
        mut list: wait_list::LockedExclusive<'wait_list, std::sync::Mutex<bool>, (), ()>,
        output: (),
    ) {
        let _ = list.wake_one(());
    }
}

pub struct Guard<'mutex, T> {
    mutex: &'mutex Mutex<T>,
}

impl<T> Deref for Guard<'_, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.mutex.data.get() }
    }
}
impl<T> DerefMut for Guard<'_, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.mutex.data.get() }
    }
}

impl<T> Drop for Guard<'_, T> {
    fn drop(&mut self) {
        let mut waiters = self.mutex.waiters.lock_exclusive();
        *waiters.guard = false;
        let _ = waiters.wake_one(());
    }
}
#

许可证:MIT

依赖关系

~0–26MB
~331K SLoC