1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use super::Mutex;
use crate::sync::atomic::{AtomicU32, Ordering::Relaxed};
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
use crate::time::Duration;

pub struct Condvar {
    // 这个原子的值只是在每次通知时递增。
    // `.wait()` 使用它在解锁互斥锁之后和等待通知之前不会错过任何通知。
    //
    futex: AtomicU32,
}

impl Condvar {
    #[inline]
    pub const fn new() -> Self {
        Self { futex: AtomicU32::new(0) }
    }

    // 这里所有的内存排序都是 `Relaxed`,因为同步是通过互斥锁的解锁和锁定来完成的。
    //

    pub fn notify_one(&self) {
        self.futex.fetch_add(1, Relaxed);
        futex_wake(&self.futex);
    }

    pub fn notify_all(&self) {
        self.futex.fetch_add(1, Relaxed);
        futex_wake_all(&self.futex);
    }

    pub unsafe fn wait(&self, mutex: &Mutex) {
        self.wait_optional_timeout(mutex, None);
    }

    pub unsafe fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> bool {
        self.wait_optional_timeout(mutex, Some(timeout))
    }

    unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>) -> bool {
        // 在我们解锁互斥锁之前检查通知计数器。
        let futex_value = self.futex.load(Relaxed);

        // 睡觉前解锁互斥锁。
        mutex.unlock();

        // 等等,但前提是我们解锁互斥锁后没有任何通知。
        //
        let r = futex_wait(&self.futex, futex_value, timeout);

        // 再次锁定互斥锁。
        mutex.lock();

        r
    }
}