]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/auxiliary/arc_wake.rs
Stabilize futures_api
[rust.git] / src / test / run-pass / auxiliary / arc_wake.rs
1 // edition:2018
2
3 use std::sync::Arc;
4 use std::task::{
5     Waker, RawWaker, RawWakerVTable,
6 };
7
8 macro_rules! waker_vtable {
9     ($ty:ident) => {
10         &RawWakerVTable::new(
11             clone_arc_raw::<$ty>,
12             wake_arc_raw::<$ty>,
13             wake_by_ref_arc_raw::<$ty>,
14             drop_arc_raw::<$ty>,
15         )
16     };
17 }
18
19 pub trait ArcWake {
20     fn wake(self: Arc<Self>);
21
22     fn wake_by_ref(arc_self: &Arc<Self>) {
23         arc_self.clone().wake()
24     }
25
26     fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
27     {
28         let ptr = Arc::into_raw(wake) as *const ();
29
30         unsafe {
31             Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
32         }
33     }
34 }
35
36 unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
37     // Retain Arc by creating a copy
38     let arc: Arc<T> = Arc::from_raw(data as *const T);
39     let arc_clone = arc.clone();
40     // Forget the Arcs again, so that the refcount isn't decrased
41     let _ = Arc::into_raw(arc);
42     let _ = Arc::into_raw(arc_clone);
43 }
44
45 unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
46     increase_refcount::<T>(data);
47     RawWaker::new(data, waker_vtable!(T))
48 }
49
50 unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
51     // Drop Arc
52     let _: Arc<T> = Arc::from_raw(data as *const T);
53 }
54
55 unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
56     let arc: Arc<T> = Arc::from_raw(data as *const T);
57     ArcWake::wake(arc);
58 }
59
60 unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
61     let arc: Arc<T> = Arc::from_raw(data as *const T);
62     ArcWake::wake_by_ref(&arc);
63     let _ = Arc::into_raw(arc);
64 }