Skip to content

Commit 25c3438

Browse files
committed
adds Schedule type
1 parent 4786f23 commit 25c3438

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

rustler/src/schedule.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use rustler_sys::c_char;
2+
3+
use crate::codegen_runtime::{NifReturnable, NifReturned};
14
use crate::wrapper::ErlNifTaskFlags;
25
use crate::Env;
36

@@ -7,7 +10,95 @@ pub enum SchedulerFlags {
710
DirtyIo = ErlNifTaskFlags::ERL_NIF_DIRTY_JOB_IO_BOUND as isize,
811
}
912

13+
impl SchedulerFlags {
14+
fn from(n: isize) -> Self {
15+
match n {
16+
_ if n == Self::Normal as isize => Self::Normal,
17+
_ if n == Self::DirtyCpu as isize => Self::DirtyCpu,
18+
_ if n == Self::DirtyIo as isize => Self::DirtyIo,
19+
_ => unreachable!(),
20+
}
21+
}
22+
}
23+
1024
pub fn consume_timeslice(env: Env, percent: i32) -> bool {
1125
let success = unsafe { rustler_sys::enif_consume_timeslice(env.as_c_arg(), percent) };
1226
success == 1
1327
}
28+
29+
/// Convenience type for scheduling a future invokation of a NIF.
30+
///
31+
/// ## Usage:
32+
///
33+
/// The first generic type should be the NIF that will be scheduled, with a
34+
/// current limitation being that it must be same throughout the lifetime of the
35+
/// NIF.
36+
///
37+
/// The second generic type defined should be the type of the return value.
38+
///
39+
/// Every other generic type is optional, but should reflect the non-`rustler`
40+
/// arguments provided to the NIF, in the same order.
41+
///
42+
/// ## Example:
43+
/// ```rust,ignore
44+
/// #[nif]
45+
/// fn factorial(input: u32, result: Option<u32>) -> Schedule<factorial, u32, u32> {
46+
/// let result = result.unwrap_or(1);
47+
/// if input == 0 {
48+
/// Schedule::Result(result)
49+
/// } else {
50+
/// Schedule::Next2(factorial, input - 1, result * input)
51+
/// }
52+
/// }
53+
/// ```
54+
pub enum Schedule<N: crate::Nif, T, A = (), B = (), C = (), D = (), E = (), F = (), G = ()> {
55+
/// The final result type to return back to the BEAM.
56+
Result(T),
57+
/// Single- and multiple-argument variants that should reflect the scheduled
58+
/// NIF's function signature.
59+
Next(N, A),
60+
Next2(N, A, B),
61+
Next3(N, A, B, C),
62+
Next4(N, A, B, C, D),
63+
Next5(N, A, B, C, D, E),
64+
Next6(N, A, B, C, D, E, F),
65+
Next7(N, A, B, C, D, E, F, G),
66+
}
67+
68+
unsafe impl<N, T, A, B, C, D, E, F, G> NifReturnable for Schedule<N, T, A, B, C, D, E, F, G>
69+
where
70+
N: crate::Nif,
71+
T: crate::Encoder,
72+
A: crate::Encoder,
73+
B: crate::Encoder,
74+
C: crate::Encoder,
75+
D: crate::Encoder,
76+
E: crate::Encoder,
77+
F: crate::Encoder,
78+
G: crate::Encoder,
79+
{
80+
#[inline]
81+
unsafe fn into_returned(self, env: Env) -> NifReturned {
82+
macro_rules! branch {
83+
($($arg:tt),*) => (
84+
NifReturned::Reschedule {
85+
fun_name: std::ffi::CStr::from_ptr(N::NAME as *const c_char).into(),
86+
flags: SchedulerFlags::from(N::FLAGS as isize),
87+
fun: N::RAW_FUNC,
88+
args: vec![$($arg.encode(env).as_c_arg()),*],
89+
}
90+
)
91+
}
92+
93+
match self {
94+
Self::Result(res) => NifReturned::Term(res.encode(env).as_c_arg()),
95+
Self::Next(_, a) => branch!(a),
96+
Self::Next2(_, a, b) => branch!(a, b),
97+
Self::Next3(_, a, b, c) => branch!(a, b, c),
98+
Self::Next4(_, a, b, c, d) => branch!(a, b, c, d),
99+
Self::Next5(_, a, b, c, d, e) => branch!(a, b, c, d, e),
100+
Self::Next6(_, a, b, c, d, e, f) => branch!(a, b, c, d, e, f),
101+
Self::Next7(_, a, b, c, d, e, f, g) => branch!(a, b, c, d, e, f, g),
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)