aboutsummaryrefslogtreecommitdiff
path: root/tests/arc_wake.rs
blob: 1940e4f98bfe8181444daccf255f8ccf0ffbdeb2 (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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use futures::task::{self, ArcWake, Waker};
use std::sync::{Arc, Mutex};

struct CountingWaker {
    nr_wake: Mutex<i32>,
}

impl CountingWaker {
    fn new() -> CountingWaker {
        CountingWaker {
            nr_wake: Mutex::new(0),
        }
    }

    fn wakes(&self) -> i32 {
        *self.nr_wake.lock().unwrap()
    }
}

impl ArcWake for CountingWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        let mut lock = arc_self.nr_wake.lock().unwrap();
        *lock += 1;
    }
}

#[test]
fn create_waker_from_arc() {
    let some_w = Arc::new(CountingWaker::new());

    let w1: Waker = task::waker(some_w.clone());
    assert_eq!(2, Arc::strong_count(&some_w));
    w1.wake_by_ref();
    assert_eq!(1, some_w.wakes());

    let w2 = w1.clone();
    assert_eq!(3, Arc::strong_count(&some_w));

    w2.wake_by_ref();
    assert_eq!(2, some_w.wakes());

    drop(w2);
    assert_eq!(2, Arc::strong_count(&some_w));
    drop(w1);
    assert_eq!(1, Arc::strong_count(&some_w));
}

struct PanicWaker;

impl ArcWake for PanicWaker {
    fn wake_by_ref(_arc_self: &Arc<Self>) {
        panic!("WAKE UP");
    }
}

#[test]
fn proper_refcount_on_wake_panic() {
    let some_w = Arc::new(PanicWaker);

    let w1: Waker = task::waker(some_w.clone());
    assert_eq!("WAKE UP", *std::panic::catch_unwind(|| w1.wake_by_ref()).unwrap_err().downcast::<&str>().unwrap());
    assert_eq!(2, Arc::strong_count(&some_w)); // some_w + w1
    drop(w1);
    assert_eq!(1, Arc::strong_count(&some_w)); // some_w
}

#[test]
fn waker_ref_wake_same() {
    let some_w = Arc::new(CountingWaker::new());

    let w1: Waker = task::waker(some_w.clone());
    let w2 = task::waker_ref(&some_w);
    let w3 = w2.clone();

    assert!(w1.will_wake(&w2));
    assert!(w2.will_wake(&w3));
}