From e20ef1a427d01c5190cb880d2d505bfde23b3aa5 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 14 Jun 2025 14:06:55 +0800 Subject: [PATCH 1/5] Remove useless scope for non-chili --- crates/par-core/src/lib.rs | 277 ++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 144 deletions(-) diff --git a/crates/par-core/src/lib.rs b/crates/par-core/src/lib.rs index c0bc17f..3ae1afe 100644 --- a/crates/par-core/src/lib.rs +++ b/crates/par-core/src/lib.rs @@ -51,195 +51,184 @@ //! par-core = { version = "1.0.1", default-features = false } //! ``` -#![cfg_attr(not(feature = "chili"), allow(unused_variables))] - -use std::{cell::RefCell, mem::transmute}; - #[cfg(all(not(feature = "chili"), not(feature = "rayon"), feature = "parallel"))] compile_error!("You must enable `chili` or `rayon` feature if you want to use `parallel` feature"); #[cfg(all(feature = "chili", feature = "rayon"))] compile_error!("You must enable `chili` or `rayon` feature, not both"); -#[derive(Default)] -pub struct MaybeScope<'a>(ScopeLike<'a>); +#[cfg(feature = "chili")] +mod par_chili { + use std::{cell::RefCell, mem::transmute}; -enum ScopeLike<'a> { - Scope(Scope<'a>), - #[cfg(feature = "chili")] - Global(Option>), -} + thread_local! { + static SCOPE: RefCell>> = Default::default(); + } + + #[derive(Default)] + pub struct MaybeScope<'a>(ScopeLike<'a>); -impl Default for ScopeLike<'_> { - fn default() -> Self { + pub struct Scope<'a>(&'a mut chili::Scope<'a>); + + enum ScopeLike<'a> { + Scope(Scope<'a>), #[cfg(feature = "chili")] - { + Global(Option>), + } + + impl Default for ScopeLike<'_> { + fn default() -> Self { ScopeLike::Global(None) } + } - #[cfg(not(feature = "chili"))] + impl<'a> MaybeScope<'a> { + #[allow(clippy::redundant_closure)] + pub fn with(&mut self, f: F) -> R + where + F: FnOnce(Scope<'a>) -> R, { - ScopeLike::Scope(Scope(std::marker::PhantomData)) + #[cfg(feature = "chili")] + let scope: &mut chili::Scope = match &mut self.0 { + ScopeLike::Scope(scope) => unsafe { + // Safety: chili Scope will be alive until the end of the function, because it's + // contract of 'a lifetime in the type. + + transmute::<&mut chili::Scope, &mut chili::Scope>(&mut scope.0) + }, + #[cfg(feature = "chili")] + ScopeLike::Global(global_scope) => { + // Initialize global scope lazily, and only once. + let scope = global_scope.get_or_insert_with(|| chili::Scope::global()); + + unsafe { + // Safety: Global scope is not dropped until the end of the program, and no + // one can access this **instance** of the global + // scope in the same time. + transmute::<&mut chili::Scope, &mut chili::Scope>(scope) + } + } + }; + + #[cfg(feature = "chili")] + let scope = Scope(scope); + + f(scope) } } -} -impl<'a> From> for MaybeScope<'a> { - fn from(value: Scope<'a>) -> Self { - MaybeScope(ScopeLike::Scope(value)) + #[inline] + pub fn join_maybe_scoped<'a, A, B, RA, RB>( + scope: &mut MaybeScope<'a>, + oper_a: A, + oper_b: B, + ) -> (RA, RB) + where + A: Send + FnOnce(Scope<'a>) -> RA, + B: Send + FnOnce(Scope<'a>) -> RB, + RA: Send, + RB: Send, + { + scope.with(|scope| join_scoped(scope, oper_a, oper_b)) } -} -impl<'a> MaybeScope<'a> { - #[allow(clippy::redundant_closure)] - pub fn with(&mut self, f: F) -> R + #[inline] + pub fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) where - F: FnOnce(Scope<'a>) -> R, + A: Send + FnOnce(Scope<'a>) -> RA, + B: Send + FnOnce(Scope<'a>) -> RB, + RA: Send, + RB: Send, { #[cfg(feature = "chili")] - let scope: &mut chili::Scope = match &mut self.0 { - ScopeLike::Scope(scope) => unsafe { - // Safety: chili Scope will be alive until the end of the function, because it's - // contract of 'a lifetime in the type. - transmute::<&mut chili::Scope, &mut chili::Scope>(&mut scope.0) - }, - #[cfg(feature = "chili")] - ScopeLike::Global(global_scope) => { - // Initialize global scope lazily, and only once. - let scope = global_scope.get_or_insert_with(|| chili::Scope::global()); - - unsafe { - // Safety: Global scope is not dropped until the end of the program, and no one - // can access this **instance** of the global scope in the same time. + let (ra, rb) = scope.0.join( + |scope| { + let scope = Scope(unsafe { + // Safety: This can be dangerous if the user do transmute on the scope, but it's + // not our fault if the user uses transmute. transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - } - } - }; - - #[cfg(feature = "chili")] - let scope = Scope(scope); - - #[cfg(not(feature = "chili"))] - let scope = Scope(std::marker::PhantomData); + }); - f(scope) - } -} - -#[cfg(not(feature = "chili"))] -pub struct Scope<'a>(std::marker::PhantomData<&'a mut &'a ()>); + oper_a(scope) + }, + |scope| { + let scope = Scope(unsafe { + // Safety: This can be dangerous if the user do transmute on the scope, but it's + // not our fault if the user uses transmute. + transmute::<&mut chili::Scope, &mut chili::Scope>(scope) + }); -#[cfg(feature = "chili")] -pub struct Scope<'a>(&'a mut chili::Scope<'a>); + oper_b(scope) + }, + ); -#[inline] -pub fn join(oper_a: A, oper_b: B) -> (RA, RB) -where - A: Send + FnOnce() -> RA, - B: Send + FnOnce() -> RB, - RA: Send, - RB: Send, -{ - thread_local! { - static SCOPE: RefCell>> = Default::default(); + (ra, rb) } - struct RemoveScopeGuard; + #[inline] + pub fn join(oper_a: A, oper_b: B) -> (RA, RB) + where + A: Send + FnOnce() -> RA, + B: Send + FnOnce() -> RB, + RA: Send, + RB: Send, + { + struct RemoveScopeGuard; - impl Drop for RemoveScopeGuard { - fn drop(&mut self) { - SCOPE.set(None); + impl Drop for RemoveScopeGuard { + fn drop(&mut self) { + SCOPE.set(None); + } } - } - - let mut scope = SCOPE.take().unwrap_or_default(); - let (ra, rb) = join_maybe_scoped( - &mut scope, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - - oper_a() - }, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); + let mut scope = SCOPE.take().unwrap_or_default(); - oper_b() - }, - ); + let (ra, rb) = join_maybe_scoped( + &mut scope, + |scope| { + let scope = unsafe { + // Safety: inner scope cannot outlive the outer scope + transmute::(scope) + }; + let _guard = RemoveScopeGuard; + SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - // In case of panic, we does not restore the scope so it will be None. - SCOPE.set(Some(scope)); + oper_a() + }, + |scope| { + let scope = unsafe { + // Safety: inner scope cannot outlive the outer scope + transmute::(scope) + }; + let _guard = RemoveScopeGuard; + SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); + + oper_b() + }, + ); - (ra, rb) -} + // In case of panic, we does not restore the scope so it will be None. + SCOPE.set(Some(scope)); -#[inline] -pub fn join_maybe_scoped<'a, A, B, RA, RB>( - scope: &mut MaybeScope<'a>, - oper_a: A, - oper_b: B, -) -> (RA, RB) -where - A: Send + FnOnce(Scope<'a>) -> RA, - B: Send + FnOnce(Scope<'a>) -> RB, - RA: Send, - RB: Send, -{ - scope.with(|scope| join_scoped(scope, oper_a, oper_b)) + (ra, rb) + } } -#[inline] -pub fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) +pub fn join(oper_a: A, oper_b: B) -> (RA, RB) where - A: Send + FnOnce(Scope<'a>) -> RA, - B: Send + FnOnce(Scope<'a>) -> RB, + A: Send + FnOnce() -> RA, + B: Send + FnOnce() -> RB, RA: Send, RB: Send, { #[cfg(feature = "chili")] - let (ra, rb) = scope.0.join( - |scope| { - let scope = Scope(unsafe { - // Safety: This can be dangerous if the user do transmute on the scope, but it's - // not our fault if the user uses transmute. - transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - }); - - oper_a(scope) - }, - |scope| { - let scope = Scope(unsafe { - // Safety: This can be dangerous if the user do transmute on the scope, but it's - // not our fault if the user uses transmute. - transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - }); - - oper_b(scope) - }, - ); + let (ra, rb) = par_chili::join(oper_a, oper_b); #[cfg(feature = "rayon")] - let (ra, rb) = rayon::join( - || oper_a(Scope(std::marker::PhantomData)), - || oper_b(Scope(std::marker::PhantomData)), - ); + let (ra, rb) = rayon::join(oper_a, oper_b); #[cfg(not(feature = "parallel"))] - let (ra, rb) = ( - oper_a(Scope(std::marker::PhantomData)), - oper_b(Scope(std::marker::PhantomData)), - ); + let (ra, rb) = (oper_a(), oper_b()); (ra, rb) } From ed98182da5839df8b9e8f6d8c984437e508901e2 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 14 Jun 2025 14:07:46 +0800 Subject: [PATCH 2/5] Remove useless flag --- crates/par-core/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/par-core/src/lib.rs b/crates/par-core/src/lib.rs index 3ae1afe..1ee2f44 100644 --- a/crates/par-core/src/lib.rs +++ b/crates/par-core/src/lib.rs @@ -72,7 +72,6 @@ mod par_chili { enum ScopeLike<'a> { Scope(Scope<'a>), - #[cfg(feature = "chili")] Global(Option>), } @@ -88,7 +87,6 @@ mod par_chili { where F: FnOnce(Scope<'a>) -> R, { - #[cfg(feature = "chili")] let scope: &mut chili::Scope = match &mut self.0 { ScopeLike::Scope(scope) => unsafe { // Safety: chili Scope will be alive until the end of the function, because it's @@ -96,7 +94,6 @@ mod par_chili { transmute::<&mut chili::Scope, &mut chili::Scope>(&mut scope.0) }, - #[cfg(feature = "chili")] ScopeLike::Global(global_scope) => { // Initialize global scope lazily, and only once. let scope = global_scope.get_or_insert_with(|| chili::Scope::global()); @@ -110,7 +107,6 @@ mod par_chili { } }; - #[cfg(feature = "chili")] let scope = Scope(scope); f(scope) @@ -140,7 +136,6 @@ mod par_chili { RA: Send, RB: Send, { - #[cfg(feature = "chili")] let (ra, rb) = scope.0.join( |scope| { let scope = Scope(unsafe { From 26d5305f2892171601bf76a5257d1a0ca9dae3e2 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 14 Jun 2025 14:09:13 +0800 Subject: [PATCH 3/5] Remove inner pub --- crates/par-core/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/par-core/src/lib.rs b/crates/par-core/src/lib.rs index 1ee2f44..3880665 100644 --- a/crates/par-core/src/lib.rs +++ b/crates/par-core/src/lib.rs @@ -66,9 +66,9 @@ mod par_chili { } #[derive(Default)] - pub struct MaybeScope<'a>(ScopeLike<'a>); + struct MaybeScope<'a>(ScopeLike<'a>); - pub struct Scope<'a>(&'a mut chili::Scope<'a>); + struct Scope<'a>(&'a mut chili::Scope<'a>); enum ScopeLike<'a> { Scope(Scope<'a>), @@ -83,7 +83,7 @@ mod par_chili { impl<'a> MaybeScope<'a> { #[allow(clippy::redundant_closure)] - pub fn with(&mut self, f: F) -> R + fn with(&mut self, f: F) -> R where F: FnOnce(Scope<'a>) -> R, { @@ -114,7 +114,7 @@ mod par_chili { } #[inline] - pub fn join_maybe_scoped<'a, A, B, RA, RB>( + fn join_maybe_scoped<'a, A, B, RA, RB>( scope: &mut MaybeScope<'a>, oper_a: A, oper_b: B, @@ -129,7 +129,7 @@ mod par_chili { } #[inline] - pub fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) + fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) where A: Send + FnOnce(Scope<'a>) -> RA, B: Send + FnOnce(Scope<'a>) -> RB, From 9480a6ead37ef1ed3e28b67b1e8b5ee8c54e908c Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 14 Jun 2025 14:11:47 +0800 Subject: [PATCH 4/5] Remove useless join fn --- crates/par-core/src/lib.rs | 65 +++++++++++++++----------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/crates/par-core/src/lib.rs b/crates/par-core/src/lib.rs index 3880665..ed5ed5a 100644 --- a/crates/par-core/src/lib.rs +++ b/crates/par-core/src/lib.rs @@ -113,21 +113,6 @@ mod par_chili { } } - #[inline] - fn join_maybe_scoped<'a, A, B, RA, RB>( - scope: &mut MaybeScope<'a>, - oper_a: A, - oper_b: B, - ) -> (RA, RB) - where - A: Send + FnOnce(Scope<'a>) -> RA, - B: Send + FnOnce(Scope<'a>) -> RB, - RA: Send, - RB: Send, - { - scope.with(|scope| join_scoped(scope, oper_a, oper_b)) - } - #[inline] fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) where @@ -176,31 +161,33 @@ mod par_chili { } } - let mut scope = SCOPE.take().unwrap_or_default(); + let mut scope: MaybeScope<'_> = SCOPE.take().unwrap_or_default(); - let (ra, rb) = join_maybe_scoped( - &mut scope, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - - oper_a() - }, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - - oper_b() - }, - ); + let (ra, rb) = scope.with(|scope| { + join_scoped( + scope, + |scope| { + let scope = unsafe { + // Safety: inner scope cannot outlive the outer scope + transmute::(scope) + }; + let _guard = RemoveScopeGuard; + SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); + + oper_a() + }, + |scope| { + let scope = unsafe { + // Safety: inner scope cannot outlive the outer scope + transmute::(scope) + }; + let _guard = RemoveScopeGuard; + SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); + + oper_b() + }, + ) + }); // In case of panic, we does not restore the scope so it will be None. SCOPE.set(Some(scope)); From a9219e191ead8bbb59a29bcdcc311b91fcc55b62 Mon Sep 17 00:00:00 2001 From: CPunisher <1343316114@qq.com> Date: Sat, 14 Jun 2025 17:24:51 +0800 Subject: [PATCH 5/5] Refactor --- crates/par-core/src/lib.rs | 135 ++++++++----------------------------- 1 file changed, 29 insertions(+), 106 deletions(-) diff --git a/crates/par-core/src/lib.rs b/crates/par-core/src/lib.rs index ed5ed5a..e4efd90 100644 --- a/crates/par-core/src/lib.rs +++ b/crates/par-core/src/lib.rs @@ -61,88 +61,42 @@ compile_error!("You must enable `chili` or `rayon` feature, not both"); mod par_chili { use std::{cell::RefCell, mem::transmute}; - thread_local! { - static SCOPE: RefCell>> = Default::default(); - } - - #[derive(Default)] - struct MaybeScope<'a>(ScopeLike<'a>); - - struct Scope<'a>(&'a mut chili::Scope<'a>); - - enum ScopeLike<'a> { - Scope(Scope<'a>), - Global(Option>), - } - - impl Default for ScopeLike<'_> { - fn default() -> Self { - ScopeLike::Global(None) - } - } - - impl<'a> MaybeScope<'a> { - #[allow(clippy::redundant_closure)] - fn with(&mut self, f: F) -> R - where - F: FnOnce(Scope<'a>) -> R, - { - let scope: &mut chili::Scope = match &mut self.0 { - ScopeLike::Scope(scope) => unsafe { - // Safety: chili Scope will be alive until the end of the function, because it's - // contract of 'a lifetime in the type. - - transmute::<&mut chili::Scope, &mut chili::Scope>(&mut scope.0) - }, - ScopeLike::Global(global_scope) => { - // Initialize global scope lazily, and only once. - let scope = global_scope.get_or_insert_with(|| chili::Scope::global()); + use chili::Scope; - unsafe { - // Safety: Global scope is not dropped until the end of the program, and no - // one can access this **instance** of the global - // scope in the same time. - transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - } - } - }; - - let scope = Scope(scope); - - f(scope) - } + thread_local! { + static SCOPE: RefCell>> = Default::default(); } #[inline] - fn join_scoped<'a, A, B, RA, RB>(scope: Scope<'a>, oper_a: A, oper_b: B) -> (RA, RB) + fn join_scoped(scope: &mut Scope<'_>, oper_a: A, oper_b: B) -> (RA, RB) where - A: Send + FnOnce(Scope<'a>) -> RA, - B: Send + FnOnce(Scope<'a>) -> RB, + A: Send + FnOnce() -> RA, + B: Send + FnOnce() -> RB, RA: Send, RB: Send, { - let (ra, rb) = scope.0.join( + scope.join( |scope| { - let scope = Scope(unsafe { - // Safety: This can be dangerous if the user do transmute on the scope, but it's - // not our fault if the user uses transmute. - transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - }); + let old_scope = SCOPE.take(); + // SATETY: it will be only accessed during `oper_a` + SCOPE.set(Some(unsafe { transmute::<&mut Scope, &mut Scope>(scope) })); + + let ra = oper_a(); + SCOPE.set(old_scope); - oper_a(scope) + ra }, |scope| { - let scope = Scope(unsafe { - // Safety: This can be dangerous if the user do transmute on the scope, but it's - // not our fault if the user uses transmute. - transmute::<&mut chili::Scope, &mut chili::Scope>(scope) - }); + let old_scope = SCOPE.take(); + // SATETY: it will be only accessed during `oper_b` + SCOPE.set(Some(unsafe { transmute::<&mut Scope, &mut Scope>(scope) })); - oper_b(scope) - }, - ); + let rb = oper_b(); + SCOPE.set(old_scope); - (ra, rb) + rb + }, + ) } #[inline] @@ -153,46 +107,15 @@ mod par_chili { RA: Send, RB: Send, { - struct RemoveScopeGuard; - - impl Drop for RemoveScopeGuard { - fn drop(&mut self) { - SCOPE.set(None); + let old_scope: Option<&mut Scope<'_>> = SCOPE.take(); + match old_scope { + Some(scope) => { + let (ra, rb) = join_scoped(scope, oper_a, oper_b); + SCOPE.set(Some(scope)); + (ra, rb) } + None => join_scoped(&mut Scope::global(), oper_a, oper_b), } - - let mut scope: MaybeScope<'_> = SCOPE.take().unwrap_or_default(); - - let (ra, rb) = scope.with(|scope| { - join_scoped( - scope, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - - oper_a() - }, - |scope| { - let scope = unsafe { - // Safety: inner scope cannot outlive the outer scope - transmute::(scope) - }; - let _guard = RemoveScopeGuard; - SCOPE.set(Some(MaybeScope(ScopeLike::Scope(scope)))); - - oper_b() - }, - ) - }); - - // In case of panic, we does not restore the scope so it will be None. - SCOPE.set(Some(scope)); - - (ra, rb) } }