Skip to content

Commit c91ab64

Browse files
committed
Add extra arc_wake
1 parent 79816bb commit c91ab64

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
}

0 commit comments

Comments
 (0)