diff options
author | 2021-05-06 19:40:37 +0200 | |
---|---|---|
committer | 2021-05-06 19:40:37 +0200 | |
commit | b4509bdbfe7cd5accf4c6b791a18ca55183a4993 (patch) | |
tree | 77d5cf702a9be6afa123844af07f316338527714 /macros/src | |
parent | aad8f81991c3495f225df80d7c8456faecd40728 (diff) | |
download | rtic-b4509bdbfe7cd5accf4c6b791a18ca55183a4993.tar.gz rtic-b4509bdbfe7cd5accf4c6b791a18ca55183a4993.tar.zst rtic-b4509bdbfe7cd5accf4c6b791a18ca55183a4993.zip |
Flattened the _ out of it
Diffstat (limited to 'macros/src')
-rw-r--r-- | macros/src/codegen.rs | 17 | ||||
-rw-r--r-- | macros/src/codegen/dispatchers.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/hardware_tasks.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/idle.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/init.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 214 | ||||
-rw-r--r-- | macros/src/codegen/pre_init.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 6 | ||||
-rw-r--r-- | macros/src/codegen/util.rs | 29 |
9 files changed, 144 insertions, 142 deletions
diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index de11cce4..113d17f9 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -97,8 +97,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let user_code = &app.user_code; let name = &app.name; let device = &extra.device; - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; let monotonic_parts: Vec<_> = app .monotonics @@ -106,7 +104,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { .map(|(_, monotonic)| { let name = &monotonic.ident; let name_str = &name.to_string(); - let ty = &monotonic.ty; let ident = util::monotonic_ident(&name_str); let ident = util::mark_internal_ident(&ident); let panic_str = &format!( @@ -117,7 +114,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { "This module holds the static implementation for `{}::now()`", name_str ); - let user_imports = &app.user_imports; let default_monotonic = if monotonic.args.default { quote!(pub use #name::now;) @@ -131,17 +127,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { #[doc = #doc] #[allow(non_snake_case)] pub mod #name { - #( - #[allow(unused_imports)] - #user_imports - )* /// Read the current time from this monotonic - pub fn now() -> rtic::time::Instant<#ty> { + pub fn now() -> rtic::time::Instant<super::super::#name> { rtic::export::interrupt::free(|_| { use rtic::Monotonic as _; use rtic::time::Clock as _; - if let Some(m) = unsafe{ #app_path::#ident.get_mut_unchecked() } { + if let Some(m) = unsafe{ super::super::#ident.get_mut_unchecked() } { if let Ok(v) = m.try_now() { v } else { @@ -163,11 +155,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { /// Holds static methods for each monotonic. pub mod monotonics { - #( - #[allow(unused_imports)] - #user_imports - )* - #(#monotonic_parts)* } ) diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 382e33fe..65a3f5f6 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -82,8 +82,6 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea quote!(#name::Locals::new(),) }; - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; quote!( #(#cfgs)* #t::#name => { @@ -95,7 +93,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea .read(); #fq.get_mut_unchecked().split().0.enqueue_unchecked(index); let priority = &rtic::export::Priority::new(PRIORITY); - #app_path::#name( + #name( #locals_new #name::Context::new(priority) #(,#pats)* diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index 540b95e5..003660c7 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -40,8 +40,6 @@ pub fn codegen( let cfgs = &task.cfgs; let attrs = &task.attrs; - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; mod_app.push(quote!( #[allow(non_snake_case)] #[no_mangle] @@ -51,7 +49,7 @@ pub fn codegen( const PRIORITY: u8 = #priority; rtic::export::run(PRIORITY, || { - #app_path::#name( + #name( #locals_new #name::Context::new(&rtic::export::Priority::new(PRIORITY)) ) diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs index b1d2e00b..4bc41c13 100644 --- a/macros/src/codegen/idle.rs +++ b/macros/src/codegen/idle.rs @@ -74,10 +74,8 @@ pub fn codegen( } )); - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; let locals_new = locals_new.iter(); - let call_idle = quote!(#app_path::#name( + let call_idle = quote!(#name( #(#locals_new,)* #name::Context::new(&rtic::export::Priority::new(0)) )); diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index aa9adcb0..fe8a1263 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -65,11 +65,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult { mod_app = Some(constructor); } - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; let locals_new = locals_new.iter(); let call_init = Some( - quote!(let (late, mut monotonics) = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));), + quote!(let (late, mut monotonics) = #name(#(#locals_new,)* #name::Context::new(core.into()));), ); root_init.push(module::codegen( diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 9bcc8f64..2f6ec335 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -1,9 +1,8 @@ +use crate::{analyze::Analysis, check::Extra, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::{ast::App, Context}; -use crate::{analyze::Analysis, check::Extra, codegen::util}; - pub fn codegen( ctxt: Context, resources_tick: bool, @@ -12,48 +11,13 @@ pub fn codegen( extra: &Extra, ) -> TokenStream2 { let mut items = vec![]; + let mut module_items = vec![]; let mut fields = vec![]; let mut values = vec![]; // Used to copy task cfgs to the whole module let mut task_cfgs = vec![]; let name = ctxt.ident(app); - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; - - let all_task_imports: Vec<_> = app - .software_tasks - .iter() - .map(|(name, st)| { - if !st.is_extern { - let cfgs = &st.cfgs; - quote! { - #(#cfgs)* - #[allow(unused_imports)] - use #app_path::#name as #name; - } - } else { - quote!() - } - }) - .chain(app.hardware_tasks.iter().map(|(name, ht)| { - if !ht.is_extern { - quote! { - #[allow(unused_imports)] - use #app_path::#name as #name; - } - } else { - quote!() - } - })) - .chain(app.user_types.iter().map(|ty| { - let t = &ty.ident; - quote! { - #[allow(unused_imports)] - use super::#t; - } - })) - .collect(); let mut lt = None; match ctxt { @@ -94,7 +58,7 @@ pub fn codegen( if ctxt.has_locals(app) { let ident = util::locals_ident(ctxt, app); - items.push(quote!( + module_items.push(quote!( #[doc(inline)] pub use super::#ident as Locals; )); @@ -110,14 +74,14 @@ pub fn codegen( None }; - items.push(quote!( + module_items.push(quote!( #[doc(inline)] pub use super::#ident as Resources; )); fields.push(quote!( /// Resources this task has access to - pub resources: Resources<#lt> + pub resources: #name::Resources<#lt> )); let priority = if ctxt.is_init() { @@ -125,7 +89,7 @@ pub fn codegen( } else { Some(quote!(priority)) }; - values.push(quote!(resources: Resources::new(#priority))); + values.push(quote!(resources: #name::Resources::new(#priority))); } if let Context::Init = ctxt { @@ -145,13 +109,17 @@ pub fn codegen( }) .collect::<Vec<_>>(); + let internal_late_ident = util::mark_internal_name("LateResources"); items.push(quote!( /// Resources initialized at runtime #[allow(non_snake_case)] - pub struct LateResources { + pub struct #internal_late_ident { #(#late_fields),* } )); + module_items.push(quote!( + pub use super::#internal_late_ident as LateResources; + )); let monotonic_types: Vec<_> = app .monotonics @@ -162,13 +130,19 @@ pub fn codegen( }) .collect(); + let internal_monotonics_ident = util::mark_internal_name("Monotonics"); + items.push(quote!( /// Monotonics used by the system #[allow(non_snake_case)] - pub struct Monotonics( + pub struct #internal_monotonics_ident( #(pub #monotonic_types),* ); )); + + module_items.push(quote!( + pub use super::#internal_monotonics_ident as Monotonics; + )); } let doc = match ctxt { @@ -178,6 +152,19 @@ pub fn codegen( Context::SoftwareTask(_) => "Software task", }; + let v = Vec::new(); + let cfgs = match ctxt { + Context::HardwareTask(t) => { + &app.hardware_tasks[t].cfgs + // ... + }, + Context::SoftwareTask(t) => { + &app.software_tasks[t].cfgs + // ... + }, + _ => &v, + }; + let core = if ctxt.is_init() { Some(quote!(core: rtic::export::Peripherals,)) } else { @@ -190,22 +177,31 @@ pub fn codegen( Some(quote!(priority: &#lt rtic::export::Priority)) }; + let internal_context_name = util::internal_task_ident(name, "Context"); + items.push(quote!( + #(#cfgs)* /// Execution context - pub struct Context<#lt> { + pub struct #internal_context_name<#lt> { #(#fields,)* } - impl<#lt> Context<#lt> { + #(#cfgs)* + impl<#lt> #internal_context_name<#lt> { #[inline(always)] pub unsafe fn new(#core #priority) -> Self { - Context { + #internal_context_name { #(#values,)* } } } )); + module_items.push(quote!( + #(#cfgs)* + pub use super::#internal_context_name as Context; + )); + // not sure if this is the right way, maybe its backwards, // that spawn_module should put in in root @@ -234,26 +230,26 @@ pub fn codegen( .expect("RTIC-ICE: interrupt identifer not found") .0; + let internal_spawn_ident = util::internal_task_ident(name, "spawn"); + // Spawn caller items.push(quote!( - #(#all_task_imports)* - #(#cfgs)* /// Spawns the task directly - pub fn spawn(#(#args,)*) -> Result<(), #ty> { + pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { let input = #tupled; unsafe { - if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) { - #app_path::#inputs + if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) { + #inputs .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); rtic::export::interrupt::free(|_| { - #app_path::#rq.get_mut_unchecked().enqueue_unchecked((#app_path::#t::#name, index)); + #rq.get_mut_unchecked().enqueue_unchecked((#t::#name, index)); }); rtic::pend(#device::#enum_::#interrupt); @@ -266,6 +262,11 @@ pub fn codegen( })); + module_items.push(quote!( + #(#cfgs)* + pub use super::#internal_spawn_ident as spawn; + )); + // Schedule caller for (_, monotonic) in &app.monotonics { let instants = util::monotonic_instants_ident(name, &monotonic.ident); @@ -282,12 +283,6 @@ pub fn codegen( let m_isr = &monotonic.args.binds; let enum_ = util::interrupt_ident(); - if monotonic.args.default { - items.push(quote!(pub use #m::spawn_after;)); - items.push(quote!(pub use #m::spawn_at;)); - items.push(quote!(pub use #m::SpawnHandle;)); - } - let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" { ( quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()) @@ -297,49 +292,56 @@ pub fn codegen( } else { let rt_err = util::rt_err_ident(); ( - quote!(rtic::export::NVIC::unmask(#app_path::#rt_err::#enum_::#m_isr)), - quote!(rtic::pend(#app_path::#rt_err::#enum_::#m_isr)), + quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)), + quote!(rtic::pend(#rt_err::#enum_::#m_isr)), ) }; - let user_imports = &app.user_imports; let tq_marker = util::mark_internal_ident(&util::timer_queue_marker_ident()); // For future use // let doc = format!(" RTIC internal: {}:{}", file!(), line!()); // items.push(quote!(#[doc = #doc])); + let internal_spawn_handle_ident = + util::internal_monotonics_ident(name, m, "SpawnHandle"); + let internal_spawn_at_ident = util::internal_monotonics_ident(name, m, "spawn_at"); + let internal_spawn_after_ident = + util::internal_monotonics_ident(name, m, "spawn_after"); + + if monotonic.args.default { + module_items.push(quote!( + pub use #m::spawn_after; + pub use #m::spawn_at; + pub use #m::SpawnHandle; + )); + } + module_items.push(quote!( + pub mod #m { + pub use super::super::#internal_spawn_after_ident as spawn_after; + pub use super::super::#internal_spawn_at_ident as spawn_at; + pub use super::super::#internal_spawn_handle_ident as SpawnHandle; + } + )); items.push(quote!( - /// Holds methods related to this monotonic - pub mod #m { - use super::*; - #[allow(unused_imports)] - use #app_path::#tq_marker; - #[allow(unused_imports)] - use #app_path::#t; - #( - #[allow(unused_imports)] - #user_imports - )* - - pub struct SpawnHandle { + pub struct #internal_spawn_handle_ident { #[doc(hidden)] marker: u32, } - impl SpawnHandle { + impl #internal_spawn_handle_ident { pub fn cancel(self) -> Result<#ty, ()> { rtic::export::interrupt::free(|_| unsafe { - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); if let Some((_task, index)) = tq.cancel_marker(self.marker) { // Get the message - let msg = #app_path::#inputs + let msg = #inputs .get_unchecked() .get_unchecked(usize::from(index)) .as_ptr() .read(); // Return the index to the free queue - #app_path::#fq.get_mut_unchecked().split().0.enqueue_unchecked(index); + #fq.get_mut_unchecked().split().0.enqueue_unchecked(index); Ok(msg) } else { @@ -351,20 +353,20 @@ pub fn codegen( #[inline] pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()> where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>, + D::T: Into<<#mono_type as rtic::time::Clock>::T>, { - self.reschedule_at(#app_path::monotonics::#m::now() + duration) + self.reschedule_at(monotonics::#m::now() + duration) } - pub fn reschedule_at(self, instant: rtic::time::Instant<#app_path::#mono_type>) -> Result<Self, ()> + pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result<Self, ()> { rtic::export::interrupt::free(|_| unsafe { let marker = *#tq_marker.get_mut_unchecked(); *#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1); - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); - tq.update_marker(self.marker, marker, instant, || #pend).map(|_| SpawnHandle { marker }) + tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) }) } } @@ -374,39 +376,39 @@ pub fn codegen( /// /// This will use the time `Instant::new(0)` as baseline if called in `#[init]`, /// so if you use a non-resetable timer use `spawn_at` when in `#[init]` - pub fn spawn_after<D>( + pub fn #internal_spawn_after_ident<D>( duration: D #(,#args)* - ) -> Result<SpawnHandle, #ty> + ) -> Result<#name::#m::SpawnHandle, #ty> where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>, + D::T: Into<<#mono_type as rtic::time::Clock>::T>, { - let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.get_mut_unchecked().is_none() }) { + let instant = if rtic::export::interrupt::free(|_| unsafe { #m_ident.get_mut_unchecked().is_none() }) { rtic::time::Instant::new(0) } else { - #app_path::monotonics::#m::now() + monotonics::#m::now() }; - spawn_at(instant + duration #(,#untupled)*) + #internal_spawn_at_ident(instant + duration #(,#untupled)*) } #(#cfgs)* /// Spawns the task at a fixed time instant - pub fn spawn_at( - instant: rtic::time::Instant<#app_path::#mono_type> + pub fn #internal_spawn_at_ident( + instant: rtic::time::Instant<#mono_type> #(,#args)* - ) -> Result<SpawnHandle, #ty> { + ) -> Result<#name::#m::SpawnHandle, #ty> { unsafe { let input = #tupled; - if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) { - #app_path::#inputs + if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) { + #inputs .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); - #app_path::#instants + #instants .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() @@ -417,44 +419,40 @@ pub fn codegen( let nr = rtic::export::NotReady { instant, index, - task: #app_path::#t::#name, + task: #t::#name, marker, }; *#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1); - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); tq.enqueue_unchecked( nr, || #enable_interrupt, || #pend, - #app_path::#m_ident.get_mut_unchecked().as_mut()); + #m_ident.get_mut_unchecked().as_mut()); - Ok(SpawnHandle { marker }) + Ok(#name::#m::SpawnHandle { marker }) }) } else { Err(input) } } } - })); + )); } } if !items.is_empty() { - let user_imports = &app.user_imports; - quote!( + #(#items)* + #[allow(non_snake_case)] #(#task_cfgs)* #[doc = #doc] pub mod #name { - #( - #[allow(unused_imports)] - #user_imports - )* - #(#items)* + #(#module_items)* } ) } else { diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index 3a62da50..531debac 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -93,8 +93,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream // Compile time assert that this priority is supported by the device stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];)); - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; let mono_type = &monotonic.ty; if &*binds.to_string() == "SysTick" { @@ -121,7 +119,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream // Always enable monotonic interrupts if they should never be off if !<#mono_type as rtic::Monotonic>::DISABLE_INTERRUPT_ON_EMPTY_QUEUE { - rtic::export::NVIC::unmask(#app_path::#rt_err::#interrupt::#binds); + rtic::export::NVIC::unmask(#rt_err::#interrupt::#binds); } )); } diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index 14e91054..9e30d100 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -57,8 +57,6 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea let mono_type = &monotonic.ty; let m_ident = util::monotonic_ident(&monotonic_name); let m_ident = util::mark_internal_ident(&m_ident); - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; // Static variables and resource proxy { @@ -139,7 +137,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea #[allow(non_snake_case)] unsafe fn #bound_interrupt() { while let Some((task, index)) = rtic::export::interrupt::free(|_| - if let Some(mono) = #app_path::#m_ident.get_mut_unchecked().as_mut() { + if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() { (&mut *#tq.get_mut_unchecked().as_mut_ptr()).dequeue(|| #disable_isr, mono) } else { // We can only use the timer queue if `init` has returned, and it @@ -152,7 +150,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea } } - rtic::export::interrupt::free(|_| if let Some(mono) = #app_path::#m_ident.get_mut_unchecked().as_mut() { + rtic::export::interrupt::free(|_| if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() { mono.on_interrupt(); }); } diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 9ccdbf78..92c7154a 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -111,6 +111,27 @@ pub fn is_exception(name: &Ident) -> bool { ) } +/// Generate an internal identifier for monotonics +pub fn internal_monotonics_ident(task: &Ident, monotonic: &Ident, ident_name: &str) -> Ident { + Ident::new( + &format!( + "__rtic_internal_{}_{}_{}", + task.to_string(), + monotonic.to_string(), + ident_name, + ), + Span::call_site(), + ) +} + +/// Generate an internal identifier for tasks +pub fn internal_task_ident(task: &Ident, ident_name: &str) -> Ident { + Ident::new( + &format!("__rtic_internal_{}_{}", task.to_string(), ident_name,), + Span::call_site(), + ) +} + /// Mark an ident as internal pub fn mark_internal_ident(ident: &Ident) -> Ident { Ident::new( @@ -119,6 +140,14 @@ pub fn mark_internal_ident(ident: &Ident) -> Ident { ) } +/// Mark an ident as internal +pub fn mark_internal_name(name: &str) -> Ident { + Ident::new( + &format!("__rtic_internal_{}", name), + Span::call_site(), + ) +} + fn link_section_index() -> usize { static INDEX: AtomicUsize = AtomicUsize::new(0); |