Skip to content

Commit f07f82d

Browse files
committed
WIP: field reflection example
Signed-off-by: Boqun Feng <[email protected]>
1 parent f5a39b7 commit f07f82d

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

examples/field_type.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use field_projection::{
2+
compat::HasFields,
3+
field_of,
4+
marker::{Field, UnalignedField},
5+
};
6+
7+
use core::ptr::null_mut;
8+
use std::sync::Arc;
9+
10+
/// An intrusive struct to link all queued work together.
11+
pub struct Work {
12+
state: usize,
13+
func: Option<fn(*mut Work)>,
14+
next: *mut Work,
15+
}
16+
17+
pub trait WorkItem<F: Field> {
18+
fn run(&self);
19+
}
20+
21+
impl WorkItem<field_of!(Foo, work)> for Foo {
22+
fn run(&self) {
23+
println!("hello work");
24+
}
25+
}
26+
27+
impl WorkItem<field_of!(Foo, work2)> for Foo {
28+
fn run(&self) {
29+
println!("hello work2");
30+
}
31+
}
32+
33+
fn bridge<F: Field<Type = Work>>(ptr: *mut Work)
34+
where
35+
F::Base: WorkItem<F> + Sized,
36+
{
37+
let ptr = unsafe { ptr.byte_sub(F::OFFSET) }.cast::<F::Base>();
38+
39+
unsafe { &*ptr }.run();
40+
}
41+
42+
impl Work {
43+
/// TODO: this should return PinInit.
44+
///
45+
/// # Safety
46+
///
47+
/// Callers must guarantee the `Work` is the exact field described by `F`.
48+
pub const unsafe fn new<F: Field<Type = Work>>() -> Self
49+
where
50+
F::Base: WorkItem<F> + Sized,
51+
{
52+
Self {
53+
state: 0,
54+
func: Some(bridge::<F>),
55+
next: null_mut(),
56+
}
57+
}
58+
}
59+
60+
#[derive(HasFields)]
61+
pub struct Foo {
62+
a: i32,
63+
b: i32,
64+
work: Work,
65+
work2: Work,
66+
}
67+
68+
impl Foo {
69+
pub fn new_arc(a: i32, b: i32) -> Arc<Self> {
70+
Arc::new(Self {
71+
a,
72+
b,
73+
// SAFETY: `work` is Foo::work.
74+
work: unsafe { Work::new::<field_of!(Foo, work)>() },
75+
// SAFETY: `work2` is Foo::work2.
76+
work2: unsafe { Work::new::<field_of!(Foo, work2)>() },
77+
})
78+
}
79+
}
80+
81+
pub trait WorkItemPointer<F: Field<Type = Work>>: Sized {
82+
// Simulates RawWorkItem
83+
fn into_work(self) -> *mut Work;
84+
85+
fn c_run(ptr: *mut Work);
86+
}
87+
88+
impl<T, F: Field<Base = T, Type = Work>> WorkItemPointer<F> for Arc<T>
89+
where
90+
T: WorkItem<F>,
91+
{
92+
fn into_work(self) -> *mut Work {
93+
let ptr = Arc::into_raw(self);
94+
unsafe { ptr.byte_add(F::OFFSET).cast_mut().cast() }
95+
}
96+
97+
fn c_run(ptr: *mut Work) {
98+
let ptr = unsafe { ptr.byte_sub(F::OFFSET).cast::<T>() };
99+
100+
let arc = unsafe { Arc::from_raw(ptr) };
101+
102+
arc.run();
103+
}
104+
}
105+
106+
/// # Safety
107+
///
108+
/// `work` must point to a valid pointer of `Work`.
109+
unsafe fn c_run_work(work: *mut Work) {
110+
if let Some(func) = unsafe { (*work).func } {
111+
func(work)
112+
}
113+
}
114+
115+
pub fn queue_work<F: Field<Base = T, Type = Work>, T: WorkItem<F>, P: WorkItemPointer<F>>(p: P) {
116+
// Simulate queue work and run
117+
//
118+
// TODO: simulate linking work and execute them all together.
119+
let ptr = p.into_work();
120+
121+
// SAFETY: `ptr` is a valid pointer of `Work`.
122+
unsafe { c_run_work(ptr) };
123+
}
124+
125+
#[test]
126+
fn main() {
127+
let foo = Foo::new_arc(12, 42);
128+
let foo2 = Foo::new_arc(12, 42);
129+
130+
queue_work::<field_of!(Foo, work), _, _>(foo);
131+
queue_work::<field_of!(Foo, work2), _, _>(foo2);
132+
}

0 commit comments

Comments
 (0)