From bb6d59cc9b1a64a62c9bc52278cd82f8509e0d1d Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 20:42:09 -0500 Subject: [PATCH 01/11] adds Schedule type --- rustler/src/schedule.rs | 91 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index ccc5de1c..7202f0c8 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -1,3 +1,6 @@ +use rustler_sys::c_char; + +use crate::codegen_runtime::{NifReturnable, NifReturned}; use crate::wrapper::ErlNifTaskFlags; use crate::Env; @@ -7,7 +10,95 @@ pub enum SchedulerFlags { DirtyIo = ErlNifTaskFlags::ERL_NIF_DIRTY_JOB_IO_BOUND as isize, } +impl SchedulerFlags { + fn from(n: isize) -> Self { + match n { + _ if n == Self::Normal as isize => Self::Normal, + _ if n == Self::DirtyCpu as isize => Self::DirtyCpu, + _ if n == Self::DirtyIo as isize => Self::DirtyIo, + _ => unreachable!(), + } + } +} + pub fn consume_timeslice(env: Env, percent: i32) -> bool { let success = unsafe { rustler_sys::enif_consume_timeslice(env.as_c_arg(), percent) }; success == 1 } + +/// Convenience type for scheduling a future invokation of a NIF. +/// +/// ## Usage: +/// +/// The first generic type should be the NIF that will be scheduled, with a +/// current limitation being that it must be same throughout the lifetime of the +/// NIF. +/// +/// The second generic type defined should be the type of the return value. +/// +/// Every other generic type is optional, but should reflect the non-`rustler` +/// arguments provided to the NIF, in the same order. +/// +/// ## Example: +/// ```rust,ignore +/// #[nif] +/// fn factorial(input: u32, result: Option) -> Schedule { +/// let result = result.unwrap_or(1); +/// if input == 0 { +/// Schedule::Result(result) +/// } else { +/// Schedule::Next2(factorial, input - 1, result * input) +/// } +/// } +/// ``` +pub enum Schedule { + /// The final result type to return back to the BEAM. + Result(T), + /// Single- and multiple-argument variants that should reflect the scheduled + /// NIF's function signature. + Next(N, A), + Next2(N, A, B), + Next3(N, A, B, C), + Next4(N, A, B, C, D), + Next5(N, A, B, C, D, E), + Next6(N, A, B, C, D, E, F), + Next7(N, A, B, C, D, E, F, G), +} + +unsafe impl NifReturnable for Schedule +where + N: crate::Nif, + T: crate::Encoder, + A: crate::Encoder, + B: crate::Encoder, + C: crate::Encoder, + D: crate::Encoder, + E: crate::Encoder, + F: crate::Encoder, + G: crate::Encoder, +{ + #[inline] + unsafe fn into_returned(self, env: Env) -> NifReturned { + macro_rules! branch { + ($($arg:tt),*) => ( + NifReturned::Reschedule { + fun_name: std::ffi::CStr::from_ptr(N::NAME as *const c_char).into(), + flags: SchedulerFlags::from(N::FLAGS as isize), + fun: N::RAW_FUNC, + args: vec![$($arg.encode(env).as_c_arg()),*], + } + ) + } + + match self { + Self::Result(res) => NifReturned::Term(res.encode(env).as_c_arg()), + Self::Next(_, a) => branch!(a), + Self::Next2(_, a, b) => branch!(a, b), + Self::Next3(_, a, b, c) => branch!(a, b, c), + Self::Next4(_, a, b, c, d) => branch!(a, b, c, d), + Self::Next5(_, a, b, c, d, e) => branch!(a, b, c, d, e), + Self::Next6(_, a, b, c, d, e, f) => branch!(a, b, c, d, e, f), + Self::Next7(_, a, b, c, d, e, f, g) => branch!(a, b, c, d, e, f, g), + } + } +} From 872755c4228e0d02ea7b0141623e7cbeec47c213 Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 21:37:52 -0500 Subject: [PATCH 02/11] adds schedule test --- rustler/src/schedule.rs | 43 ++++++++++++++----- rustler_tests/lib/rustler_test.ex | 2 + rustler_tests/native/rustler_test/src/lib.rs | 2 + .../native/rustler_test/src/test_schedule.rs | 11 +++++ rustler_tests/test/schedule_test.exs | 7 +++ 5 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 rustler_tests/native/rustler_test/src/test_schedule.rs create mode 100644 rustler_tests/test/schedule_test.exs diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index 7202f0c8..8c8278a6 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -3,6 +3,7 @@ use rustler_sys::c_char; use crate::codegen_runtime::{NifReturnable, NifReturned}; use crate::wrapper::ErlNifTaskFlags; use crate::Env; +use std::{ffi::CStr, marker::PhantomData}; pub enum SchedulerFlags { Normal = ErlNifTaskFlags::ERL_NIF_NORMAL_JOB as isize, @@ -42,12 +43,13 @@ pub fn consume_timeslice(env: Env, percent: i32) -> bool { /// ## Example: /// ```rust,ignore /// #[nif] -/// fn factorial(input: u32, result: Option) -> Schedule { +/// fn factorial(input: u32, result: Option) -> Schedule { /// let result = result.unwrap_or(1); /// if input == 0 { /// Schedule::Result(result) /// } else { -/// Schedule::Next2(factorial, input - 1, result * input) +/// // alternatively `Schedule::Next2(std::marker::PhantomData, input - 1, result * input)` +/// Schedule::next2(input - 1, result * input) /// } /// } /// ``` @@ -56,13 +58,34 @@ pub enum Schedule, A), + Next2(PhantomData, A, B), + Next3(PhantomData, A, B, C), + Next4(PhantomData, A, B, C, D), + Next5(PhantomData, A, B, C, D, E), + Next6(PhantomData, A, B, C, D, E, F), + Next7(PhantomData, A, B, C, D, E, F, G), +} + +macro_rules! impl_func { + ($variant:ident $func_name:ident($($arg:ident : $ty:ty,)*)) => { + /// Shorthand for creating a [`Schedule`] variant. + /// + /// [`Schedule`]: crate::schedule::Schedule + pub fn $func_name($($arg: $ty),*) -> Self { + Self::$variant(PhantomData, $($arg),*) + } + }; +} + +impl Schedule { + impl_func! { Next next(a: A,) } + impl_func! { Next2 next2(a: A, b: B,) } + impl_func! { Next3 next3(a: A, b: B, c: C,) } + impl_func! { Next4 next4(a: A, b: B, c: C, d: D,) } + impl_func! { Next5 next5(a: A, b: B, c: C, d: D, e: E,) } + impl_func! { Next6 next6(a: A, b: B, c: C, d: D, e: E, f: F,) } + impl_func! { Next7 next7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } } unsafe impl NifReturnable for Schedule @@ -82,7 +105,7 @@ where macro_rules! branch { ($($arg:tt),*) => ( NifReturned::Reschedule { - fun_name: std::ffi::CStr::from_ptr(N::NAME as *const c_char).into(), + fun_name: CStr::from_ptr(N::NAME as *const c_char).into(), flags: SchedulerFlags::from(N::FLAGS as isize), fun: N::RAW_FUNC, args: vec![$($arg.encode(env).as_c_arg()),*], diff --git a/rustler_tests/lib/rustler_test.ex b/rustler_tests/lib/rustler_test.ex index 1adaded7..5c895911 100644 --- a/rustler_tests/lib/rustler_test.ex +++ b/rustler_tests/lib/rustler_test.ex @@ -114,6 +114,8 @@ defmodule RustlerTest do def sum_range(_), do: err() + def scheduled_fac(_, _ \\ nil), do: err() + def bad_arg_error(), do: err() def atom_str_error(), do: err() def raise_atom_error(), do: err() diff --git a/rustler_tests/native/rustler_test/src/lib.rs b/rustler_tests/native/rustler_test/src/lib.rs index efe2372e..d07bc6b0 100644 --- a/rustler_tests/native/rustler_test/src/lib.rs +++ b/rustler_tests/native/rustler_test/src/lib.rs @@ -10,6 +10,7 @@ mod test_nif_attrs; mod test_primitives; mod test_range; mod test_resource; +mod test_schedule; mod test_term; mod test_thread; mod test_tuple; @@ -82,6 +83,7 @@ rustler::init!( test_codegen::tuplestruct_record_echo, test_dirty::dirty_cpu, test_dirty::dirty_io, + test_schedule::scheduled_fac, test_range::sum_range, test_error::bad_arg_error, test_error::atom_str_error, diff --git a/rustler_tests/native/rustler_test/src/test_schedule.rs b/rustler_tests/native/rustler_test/src/test_schedule.rs new file mode 100644 index 00000000..06fb4143 --- /dev/null +++ b/rustler_tests/native/rustler_test/src/test_schedule.rs @@ -0,0 +1,11 @@ +use rustler::schedule::Schedule; + +#[rustler::nif] +fn scheduled_fac(input: u32, result: Option) -> Schedule { + let result = result.unwrap_or(1); + if input == 0 { + Schedule::Result(result) + } else { + Schedule::next2(input - 1, result * input) + } +} diff --git a/rustler_tests/test/schedule_test.exs b/rustler_tests/test/schedule_test.exs new file mode 100644 index 00000000..26884ead --- /dev/null +++ b/rustler_tests/test/schedule_test.exs @@ -0,0 +1,7 @@ +defmodule RustlerTest.ScheduleTest do + use ExUnit.Case, async: true + + test "scheduled factorial" do + assert 24 == RustlerTest.scheduled_fac(4) + end +end From 8217e22e07712e03f7c3562e493a99ea467c23ac Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 22:00:52 -0500 Subject: [PATCH 03/11] clippy --- rustler/src/schedule.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index 8c8278a6..db27dd7c 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -113,6 +113,7 @@ where ) } + #[allow(clippy::many_single_char_names)] match self { Self::Result(res) => NifReturned::Term(res.encode(env).as_c_arg()), Self::Next(_, a) => branch!(a), From 241734db10a405b4dfd6034e68988323e97b2d2f Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 22:45:58 -0500 Subject: [PATCH 04/11] adds From impl --- rustler/src/schedule.rs | 43 ++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index db27dd7c..87f5486a 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -67,26 +67,43 @@ pub enum Schedule, A, B, C, D, E, F, G), } -macro_rules! impl_func { +macro_rules! impl_funcs { ($variant:ident $func_name:ident($($arg:ident : $ty:ty,)*)) => { - /// Shorthand for creating a [`Schedule`] variant. - /// - /// [`Schedule`]: crate::schedule::Schedule - pub fn $func_name($($arg: $ty),*) -> Self { - Self::$variant(PhantomData, $($arg),*) + impl Schedule { + #[inline] + pub fn $func_name($($arg: $ty),*) -> Self { + Self::$variant(PhantomData, $($arg),*) + } + } + + impl From<($($ty),*)> for Schedule { + #[inline] + fn from(($($arg),*): ($($ty),*)) -> Self { + Self::$variant(PhantomData, $($arg),*) + } } }; } impl Schedule { - impl_func! { Next next(a: A,) } - impl_func! { Next2 next2(a: A, b: B,) } - impl_func! { Next3 next3(a: A, b: B, c: C,) } - impl_func! { Next4 next4(a: A, b: B, c: C, d: D,) } - impl_func! { Next5 next5(a: A, b: B, c: C, d: D, e: E,) } - impl_func! { Next6 next6(a: A, b: B, c: C, d: D, e: E, f: F,) } - impl_func! { Next7 next7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } + #[inline] + pub fn next(a: A) -> Self { + Self::from(a) + } +} + +impl From for Schedule { + #[inline] + fn from(a: A) -> Self { + Self::Next(PhantomData, a) + } } +impl_funcs! { Next2 next2(a: A, b: B,) } +impl_funcs! { Next3 next3(a: A, b: B, c: C,) } +impl_funcs! { Next4 next4(a: A, b: B, c: C, d: D,) } +impl_funcs! { Next5 next5(a: A, b: B, c: C, d: D, e: E,) } +impl_funcs! { Next6 next6(a: A, b: B, c: C, d: D, e: E, f: F,) } +impl_funcs! { Next7 next7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } unsafe impl NifReturnable for Schedule where From 83a999301f2739af450d4f610eaf99ddef0c758c Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 22:48:55 -0500 Subject: [PATCH 05/11] more clippy --- rustler/src/schedule.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index 87f5486a..75d85773 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -70,6 +70,7 @@ pub enum Schedule { impl Schedule { + #[allow(clippy::many_single_char_names)] #[inline] pub fn $func_name($($arg: $ty),*) -> Self { Self::$variant(PhantomData, $($arg),*) @@ -77,6 +78,7 @@ macro_rules! impl_funcs { } impl From<($($ty),*)> for Schedule { + #[allow(clippy::many_single_char_names)] #[inline] fn from(($($arg),*): ($($ty),*)) -> Self { Self::$variant(PhantomData, $($arg),*) From 862ebeecde4a0fc74db49734ab25bca3b926384c Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 25 May 2021 22:53:44 -0500 Subject: [PATCH 06/11] simplify test --- rustler/src/schedule.rs | 1 + rustler_tests/native/rustler_test/src/test_schedule.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index 75d85773..a903958a 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -49,6 +49,7 @@ pub fn consume_timeslice(env: Env, percent: i32) -> bool { /// Schedule::Result(result) /// } else { /// // alternatively `Schedule::Next2(std::marker::PhantomData, input - 1, result * input)` +/// // alternatively `(input - 1, result * input).into()` /// Schedule::next2(input - 1, result * input) /// } /// } diff --git a/rustler_tests/native/rustler_test/src/test_schedule.rs b/rustler_tests/native/rustler_test/src/test_schedule.rs index 06fb4143..1ef30c6f 100644 --- a/rustler_tests/native/rustler_test/src/test_schedule.rs +++ b/rustler_tests/native/rustler_test/src/test_schedule.rs @@ -6,6 +6,6 @@ fn scheduled_fac(input: u32, result: Option) -> Schedule Date: Tue, 25 May 2021 23:16:30 -0500 Subject: [PATCH 07/11] minor change --- rustler/src/schedule.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index a903958a..aca31588 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -12,6 +12,7 @@ pub enum SchedulerFlags { } impl SchedulerFlags { + #[inline] fn from(n: isize) -> Self { match n { _ if n == Self::Normal as isize => Self::Normal, @@ -82,7 +83,7 @@ macro_rules! impl_funcs { #[allow(clippy::many_single_char_names)] #[inline] fn from(($($arg),*): ($($ty),*)) -> Self { - Self::$variant(PhantomData, $($arg),*) + Self::$func_name($($arg),*) } } }; @@ -91,14 +92,14 @@ macro_rules! impl_funcs { impl Schedule { #[inline] pub fn next(a: A) -> Self { - Self::from(a) + Self::Next(PhantomData, a) } } impl From for Schedule { #[inline] fn from(a: A) -> Self { - Self::Next(PhantomData, a) + Self::next(a) } } impl_funcs! { Next2 next2(a: A, b: B,) } From 1b4671ced4ae3d992089932351d53542f2b451ea Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 1 Jun 2021 19:11:17 -0500 Subject: [PATCH 08/11] renames Schedule variants, adds reschedule macro --- rustler/src/lib.rs | 2 +- rustler/src/schedule.rs | 106 ++++++++---------- .../native/rustler_test/src/test_schedule.rs | 8 +- 3 files changed, 51 insertions(+), 65 deletions(-) diff --git a/rustler/src/lib.rs b/rustler/src/lib.rs index ce700ef6..4c144a8c 100644 --- a/rustler/src/lib.rs +++ b/rustler/src/lib.rs @@ -49,7 +49,7 @@ pub mod dynamic; pub use crate::dynamic::TermType; pub mod schedule; -pub use crate::schedule::SchedulerFlags; +pub use crate::schedule::{Schedule, SchedulerFlags}; pub mod env; pub use crate::env::{Env, OwnedEnv}; pub mod thread; diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index aca31588..f7d1ce1e 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -11,23 +11,19 @@ pub enum SchedulerFlags { DirtyIo = ErlNifTaskFlags::ERL_NIF_DIRTY_JOB_IO_BOUND as isize, } -impl SchedulerFlags { - #[inline] - fn from(n: isize) -> Self { - match n { - _ if n == Self::Normal as isize => Self::Normal, - _ if n == Self::DirtyCpu as isize => Self::DirtyCpu, - _ if n == Self::DirtyIo as isize => Self::DirtyIo, - _ => unreachable!(), - } - } -} - pub fn consume_timeslice(env: Env, percent: i32) -> bool { let success = unsafe { rustler_sys::enif_consume_timeslice(env.as_c_arg(), percent) }; success == 1 } +/// Convenience macro for scheduling a future invokation of a NIF. +#[macro_export] +macro_rules! reschedule { + ($flags:expr, $($arg:expr),*) => ( + rustler::schedule::Schedule::from(($flags, $($arg,)*)) + ) +} + /// Convenience type for scheduling a future invokation of a NIF. /// /// ## Usage: @@ -38,8 +34,8 @@ pub fn consume_timeslice(env: Env, percent: i32) -> bool { /// /// The second generic type defined should be the type of the return value. /// -/// Every other generic type is optional, but should reflect the non-`rustler` -/// arguments provided to the NIF, in the same order. +/// Every other generic type is optional, but should reflect the argument types +/// of the scheduled NIF, in the same order. /// /// ## Example: /// ```rust,ignore @@ -47,26 +43,28 @@ pub fn consume_timeslice(env: Env, percent: i32) -> bool { /// fn factorial(input: u32, result: Option) -> Schedule { /// let result = result.unwrap_or(1); /// if input == 0 { -/// Schedule::Result(result) +/// Schedule::Return(result) /// } else { -/// // alternatively `Schedule::Next2(std::marker::PhantomData, input - 1, result * input)` -/// // alternatively `(input - 1, result * input).into()` -/// Schedule::next2(input - 1, result * input) +/// // alternatively `Schedule::Continue2(std::marker::PhantomData, SchedulerFlags::Normal, input - 1, result * input)` +/// // alternatively `Schedule::continue2(SchedulerFlags::Normal, input - 1, result * input)` +/// // alternatively `Schedule::from((SchedulerFlags::Normal, input - 1, result * input))` +/// // alternatively `(SchedulerFlags::Normal, input - 1, result * input).into()` +/// reschedule!(SchedulerFlags::Normal, input - 1, result * input) /// } /// } /// ``` pub enum Schedule { /// The final result type to return back to the BEAM. - Result(T), + Return(T), /// Single- and multiple-argument variants that should reflect the scheduled /// NIF's function signature. - Next(PhantomData, A), - Next2(PhantomData, A, B), - Next3(PhantomData, A, B, C), - Next4(PhantomData, A, B, C, D), - Next5(PhantomData, A, B, C, D, E), - Next6(PhantomData, A, B, C, D, E, F), - Next7(PhantomData, A, B, C, D, E, F, G), + Continue(PhantomData, SchedulerFlags, A), + Continue2(PhantomData, SchedulerFlags, A, B), + Continue3(PhantomData, SchedulerFlags, A, B, C), + Continue4(PhantomData, SchedulerFlags, A, B, C, D), + Continue5(PhantomData, SchedulerFlags, A, B, C, D, E), + Continue6(PhantomData, SchedulerFlags, A, B, C, D, E, F), + Continue7(PhantomData, SchedulerFlags, A, B, C, D, E, F, G), } macro_rules! impl_funcs { @@ -74,40 +72,28 @@ macro_rules! impl_funcs { impl Schedule { #[allow(clippy::many_single_char_names)] #[inline] - pub fn $func_name($($arg: $ty),*) -> Self { - Self::$variant(PhantomData, $($arg),*) + pub fn $func_name(flags: SchedulerFlags, $($arg: $ty),*) -> Self { + Self::$variant(PhantomData, flags, $($arg),*) } } - impl From<($($ty),*)> for Schedule { + impl From<(SchedulerFlags, $($ty),*)> for Schedule { #[allow(clippy::many_single_char_names)] #[inline] - fn from(($($arg),*): ($($ty),*)) -> Self { - Self::$func_name($($arg),*) + fn from((flags, $($arg),*): (SchedulerFlags, $($ty),*)) -> Self { + Self::$func_name(flags, $($arg),*) } } }; } -impl Schedule { - #[inline] - pub fn next(a: A) -> Self { - Self::Next(PhantomData, a) - } -} - -impl From for Schedule { - #[inline] - fn from(a: A) -> Self { - Self::next(a) - } -} -impl_funcs! { Next2 next2(a: A, b: B,) } -impl_funcs! { Next3 next3(a: A, b: B, c: C,) } -impl_funcs! { Next4 next4(a: A, b: B, c: C, d: D,) } -impl_funcs! { Next5 next5(a: A, b: B, c: C, d: D, e: E,) } -impl_funcs! { Next6 next6(a: A, b: B, c: C, d: D, e: E, f: F,) } -impl_funcs! { Next7 next7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } +impl_funcs! { Continue continue1(a: A,) } +impl_funcs! { Continue2 continue2(a: A, b: B,) } +impl_funcs! { Continue3 continue3(a: A, b: B, c: C,) } +impl_funcs! { Continue4 continue4(a: A, b: B, c: C, d: D,) } +impl_funcs! { Continue5 continue5(a: A, b: B, c: C, d: D, e: E,) } +impl_funcs! { Continue6 continue6(a: A, b: B, c: C, d: D, e: E, f: F,) } +impl_funcs! { Continue7 continue7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } unsafe impl NifReturnable for Schedule where @@ -124,10 +110,10 @@ where #[inline] unsafe fn into_returned(self, env: Env) -> NifReturned { macro_rules! branch { - ($($arg:tt),*) => ( + ($flags:expr, $($arg:tt),*) => ( NifReturned::Reschedule { fun_name: CStr::from_ptr(N::NAME as *const c_char).into(), - flags: SchedulerFlags::from(N::FLAGS as isize), + flags: $flags, fun: N::RAW_FUNC, args: vec![$($arg.encode(env).as_c_arg()),*], } @@ -136,14 +122,14 @@ where #[allow(clippy::many_single_char_names)] match self { - Self::Result(res) => NifReturned::Term(res.encode(env).as_c_arg()), - Self::Next(_, a) => branch!(a), - Self::Next2(_, a, b) => branch!(a, b), - Self::Next3(_, a, b, c) => branch!(a, b, c), - Self::Next4(_, a, b, c, d) => branch!(a, b, c, d), - Self::Next5(_, a, b, c, d, e) => branch!(a, b, c, d, e), - Self::Next6(_, a, b, c, d, e, f) => branch!(a, b, c, d, e, f), - Self::Next7(_, a, b, c, d, e, f, g) => branch!(a, b, c, d, e, f, g), + Self::Return(res) => NifReturned::Term(res.encode(env).as_c_arg()), + Self::Continue(_, flags, a) => branch!(flags, a), + Self::Continue2(_, flags, a, b) => branch!(flags, a, b), + Self::Continue3(_, flags, a, b, c) => branch!(flags, a, b, c), + Self::Continue4(_, flags, a, b, c, d) => branch!(flags, a, b, c, d), + Self::Continue5(_, flags, a, b, c, d, e) => branch!(flags, a, b, c, d, e), + Self::Continue6(_, flags, a, b, c, d, e, f) => branch!(flags, a, b, c, d, e, f), + Self::Continue7(_, flags, a, b, c, d, e, f, g) => branch!(flags, a, b, c, d, e, f, g), } } } diff --git a/rustler_tests/native/rustler_test/src/test_schedule.rs b/rustler_tests/native/rustler_test/src/test_schedule.rs index 1ef30c6f..17e90c8d 100644 --- a/rustler_tests/native/rustler_test/src/test_schedule.rs +++ b/rustler_tests/native/rustler_test/src/test_schedule.rs @@ -1,11 +1,11 @@ -use rustler::schedule::Schedule; +use rustler::{reschedule, Schedule, SchedulerFlags}; #[rustler::nif] -fn scheduled_fac(input: u32, result: Option) -> Schedule { +fn scheduled_fac<'a>(input: u32, result: Option) -> Schedule { let result = result.unwrap_or(1); if input == 0 { - Schedule::Result(result) + Schedule::Return(result) } else { - (input - 1, result * input).into() + reschedule!(SchedulerFlags::Normal, input - 1, result * input) } } From cab149c38bceff8579ae1cccfb76545e9194b892 Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 1 Jun 2021 21:23:40 -0500 Subject: [PATCH 09/11] cleanup --- rustler/src/schedule.rs | 92 ++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index f7d1ce1e..db0b59d7 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -58,7 +58,7 @@ pub enum Schedule, SchedulerFlags, A), + Continue1(PhantomData, SchedulerFlags, A), Continue2(PhantomData, SchedulerFlags, A, B), Continue3(PhantomData, SchedulerFlags, A, B, C), Continue4(PhantomData, SchedulerFlags, A, B, C, D), @@ -67,69 +67,59 @@ pub enum Schedule, SchedulerFlags, A, B, C, D, E, F, G), } -macro_rules! impl_funcs { - ($variant:ident $func_name:ident($($arg:ident : $ty:ty,)*)) => { +macro_rules! impls { + ($($variant:ident $func_name:ident($($arg:ident : $ty:ty,)*);)*) => { impl Schedule { - #[allow(clippy::many_single_char_names)] + $(#[allow(clippy::many_single_char_names)] #[inline] pub fn $func_name(flags: SchedulerFlags, $($arg: $ty),*) -> Self { Self::$variant(PhantomData, flags, $($arg),*) - } + })* } - impl From<(SchedulerFlags, $($ty),*)> for Schedule { + $(impl From<(SchedulerFlags, $($ty),*)> for Schedule { #[allow(clippy::many_single_char_names)] #[inline] fn from((flags, $($arg),*): (SchedulerFlags, $($ty),*)) -> Self { Self::$func_name(flags, $($arg),*) } - } - }; -} - -impl_funcs! { Continue continue1(a: A,) } -impl_funcs! { Continue2 continue2(a: A, b: B,) } -impl_funcs! { Continue3 continue3(a: A, b: B, c: C,) } -impl_funcs! { Continue4 continue4(a: A, b: B, c: C, d: D,) } -impl_funcs! { Continue5 continue5(a: A, b: B, c: C, d: D, e: E,) } -impl_funcs! { Continue6 continue6(a: A, b: B, c: C, d: D, e: E, f: F,) } -impl_funcs! { Continue7 continue7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,) } + })* -unsafe impl NifReturnable for Schedule -where - N: crate::Nif, - T: crate::Encoder, - A: crate::Encoder, - B: crate::Encoder, - C: crate::Encoder, - D: crate::Encoder, - E: crate::Encoder, - F: crate::Encoder, - G: crate::Encoder, -{ - #[inline] - unsafe fn into_returned(self, env: Env) -> NifReturned { - macro_rules! branch { - ($flags:expr, $($arg:tt),*) => ( - NifReturned::Reschedule { - fun_name: CStr::from_ptr(N::NAME as *const c_char).into(), - flags: $flags, - fun: N::RAW_FUNC, - args: vec![$($arg.encode(env).as_c_arg()),*], + unsafe impl NifReturnable for Schedule + where + N: crate::Nif, + T: crate::Encoder, + A: crate::Encoder, + B: crate::Encoder, + C: crate::Encoder, + D: crate::Encoder, + E: crate::Encoder, + F: crate::Encoder, + G: crate::Encoder, + { + #[inline] + unsafe fn into_returned(self, env: Env) -> NifReturned { + #[allow(clippy::many_single_char_names)] + match self { + Self::Return(res) => NifReturned::Term(res.encode(env).as_c_arg()), + $(Self::$variant(_, flags, $($arg),*) => NifReturned::Reschedule { + fun_name: CStr::from_ptr(N::NAME as *const c_char).into(), + flags, + fun: N::RAW_FUNC, + args: vec![$($arg.encode(env).as_c_arg()),*], + },)* } - ) + } } + }; +} - #[allow(clippy::many_single_char_names)] - match self { - Self::Return(res) => NifReturned::Term(res.encode(env).as_c_arg()), - Self::Continue(_, flags, a) => branch!(flags, a), - Self::Continue2(_, flags, a, b) => branch!(flags, a, b), - Self::Continue3(_, flags, a, b, c) => branch!(flags, a, b, c), - Self::Continue4(_, flags, a, b, c, d) => branch!(flags, a, b, c, d), - Self::Continue5(_, flags, a, b, c, d, e) => branch!(flags, a, b, c, d, e), - Self::Continue6(_, flags, a, b, c, d, e, f) => branch!(flags, a, b, c, d, e, f), - Self::Continue7(_, flags, a, b, c, d, e, f, g) => branch!(flags, a, b, c, d, e, f, g), - } - } +impls! { + Continue1 continue1(a: A,); + Continue2 continue2(a: A, b: B,); + Continue3 continue3(a: A, b: B, c: C,); + Continue4 continue4(a: A, b: B, c: C, d: D,); + Continue5 continue5(a: A, b: B, c: C, d: D, e: E,); + Continue6 continue6(a: A, b: B, c: C, d: D, e: E, f: F,); + Continue7 continue7(a: A, b: B, c: C, d: D, e: E, f: F, g: G,); } From 39e01062ae2b4a150b604fca74dd654a5aef116f Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 1 Jun 2021 23:43:58 -0500 Subject: [PATCH 10/11] schedule doc example type clarity --- rustler/src/schedule.rs | 14 +++++++------- .../native/rustler_test/src/test_schedule.rs | 11 +++++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index db0b59d7..1ab4f048 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -20,7 +20,7 @@ pub fn consume_timeslice(env: Env, percent: i32) -> bool { #[macro_export] macro_rules! reschedule { ($flags:expr, $($arg:expr),*) => ( - rustler::schedule::Schedule::from(($flags, $($arg,)*)) + rustler::Schedule::from(($flags, $($arg,)*)) ) } @@ -40,16 +40,16 @@ macro_rules! reschedule { /// ## Example: /// ```rust,ignore /// #[nif] -/// fn factorial(input: u32, result: Option) -> Schedule { +/// fn factorial(input: u8, result: Option) -> Schedule> { /// let result = result.unwrap_or(1); /// if input == 0 { /// Schedule::Return(result) /// } else { -/// // alternatively `Schedule::Continue2(std::marker::PhantomData, SchedulerFlags::Normal, input - 1, result * input)` -/// // alternatively `Schedule::continue2(SchedulerFlags::Normal, input - 1, result * input)` -/// // alternatively `Schedule::from((SchedulerFlags::Normal, input - 1, result * input))` -/// // alternatively `(SchedulerFlags::Normal, input - 1, result * input).into()` -/// reschedule!(SchedulerFlags::Normal, input - 1, result * input) +/// // alternatively `Schedule::Continue2(std::marker::PhantomData, SchedulerFlags::Normal, input - 1, Some(result * input as u32))` +/// // or `Schedule::continue2(SchedulerFlags::Normal, input - 1, Some(result * input as u32))` +/// // or `Schedule::from((SchedulerFlags::Normal, input - 1, Some(result * input as u32)))` +/// // or `(SchedulerFlags::Normal, input - 1, Some(result * input as u32)).into()` +/// reschedule!(SchedulerFlags::Normal, input - 1, Some(result * input as u32)) /// } /// } /// ``` diff --git a/rustler_tests/native/rustler_test/src/test_schedule.rs b/rustler_tests/native/rustler_test/src/test_schedule.rs index 17e90c8d..bfb1701e 100644 --- a/rustler_tests/native/rustler_test/src/test_schedule.rs +++ b/rustler_tests/native/rustler_test/src/test_schedule.rs @@ -1,11 +1,18 @@ use rustler::{reschedule, Schedule, SchedulerFlags}; #[rustler::nif] -fn scheduled_fac<'a>(input: u32, result: Option) -> Schedule { +fn scheduled_fac<'a>( + input: u8, + result: Option, +) -> Schedule> { let result = result.unwrap_or(1); if input == 0 { Schedule::Return(result) } else { - reschedule!(SchedulerFlags::Normal, input - 1, result * input) + reschedule!( + SchedulerFlags::Normal, + input - 1, + Some(result * input as u32) + ) } } From c02e99144d8ed314c2bad537f233f4e4ffc13255 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 13 Feb 2024 16:17:16 +0100 Subject: [PATCH 11/11] Fix lints --- rustler/src/schedule.rs | 1 + rustler_tests/native/rustler_test/src/test_schedule.rs | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rustler/src/schedule.rs b/rustler/src/schedule.rs index 1ab4f048..8b5540d3 100644 --- a/rustler/src/schedule.rs +++ b/rustler/src/schedule.rs @@ -71,6 +71,7 @@ macro_rules! impls { ($($variant:ident $func_name:ident($($arg:ident : $ty:ty,)*);)*) => { impl Schedule { $(#[allow(clippy::many_single_char_names)] + #[allow(clippy::too_many_arguments)] #[inline] pub fn $func_name(flags: SchedulerFlags, $($arg: $ty),*) -> Self { Self::$variant(PhantomData, flags, $($arg),*) diff --git a/rustler_tests/native/rustler_test/src/test_schedule.rs b/rustler_tests/native/rustler_test/src/test_schedule.rs index bfb1701e..564fba3d 100644 --- a/rustler_tests/native/rustler_test/src/test_schedule.rs +++ b/rustler_tests/native/rustler_test/src/test_schedule.rs @@ -1,10 +1,7 @@ use rustler::{reschedule, Schedule, SchedulerFlags}; #[rustler::nif] -fn scheduled_fac<'a>( - input: u8, - result: Option, -) -> Schedule> { +fn scheduled_fac(input: u8, result: Option) -> Schedule> { let result = result.unwrap_or(1); if input == 0 { Schedule::Return(result)