summaryrefslogtreecommitdiffstats
path: root/tokio/src/runtime/tests/loom_oneshot.rs
blob: c126fe479afcec750e5511c5db951ca20c6a89ef (plain)
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
use loom::sync::Notify;

use std::sync::{Arc, Mutex};

pub(crate) fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let inner = Arc::new(Inner {
        notify: Notify::new(),
        value: Mutex::new(None),
    });

    let tx = Sender {
        inner: inner.clone(),
    };
    let rx = Receiver { inner };

    (tx, rx)
}

pub(crate) struct Sender<T> {
    inner: Arc<Inner<T>>,
}

pub(crate) struct Receiver<T> {
    inner: Arc<Inner<T>>,
}

struct Inner<T> {
    notify: Notify,
    value: Mutex<Option<T>>,
}

impl<T> Sender<T> {
    pub(crate) fn send(self, value: T) {
        *self.inner.value.lock().unwrap() = Some(value);
        self.inner.notify.notify();
    }
}

impl<T> Receiver<T> {
    pub(crate) fn recv(self) -> T {
        loop {
            if let Some(v) = self.inner.value.lock().unwrap().take() {
                return v;
            }

            self.inner.notify.wait();
        }
    }
}