rtic_core/codegen/
shared_resources.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};

use crate::parser::ast::{RticTask, SharedResources};
use crate::rtic_functions::get_resource_proxy_lock_fn;
use crate::rtic_traits::MUTEX_TY;
use crate::{multibin, AppArgs, CorePassBackend, SubApp};

impl SharedResources {
    pub fn generate_shared_resources_def(&self) -> TokenStream2 {
        let cfg_core = multibin::multibin_cfg_core(self.args.core);
        let shared_struct = &self.strct;
        let resources_ty = &shared_struct.ident;
        let static_instance_name = &self.name_uppercase();

        quote! {
            #cfg_core
            static mut #static_instance_name: core::mem::MaybeUninit<#resources_ty> = core::mem::MaybeUninit::uninit();
            #cfg_core
            #shared_struct
        }
    }

    pub fn generate_resource_proxies(
        &self,
        implementor: &dyn CorePassBackend,
        app_params: &AppArgs,
        app_info: &SubApp,
    ) -> TokenStream2 {
        let static_mut_shared_resources = self.name_uppercase();
        let proxies = self.resources.iter().map(|element| {
            let element_name = &element.ident;
            let element_ty = &element.ty;
            let proxy_name = utils::get_proxy_name(element_name);
            let mutex_ty = format_ident!("{}", MUTEX_TY);
            let cfg_core = multibin::multibin_cfg_core(self.args.core);

            // generate the implementation of lock function, using external implementation
            let impl_lock_fn = get_resource_proxy_lock_fn(
                implementor,
                app_params,
                app_info,
                element,
                &static_mut_shared_resources,
            );

            quote! {
                // Resource proxy for `#element_name`
                #cfg_core
                pub struct #proxy_name {
                    #[doc(hidden)]
                    task_priority: u16,
                }

                #cfg_core
                impl #proxy_name {
                    #[inline(always)]
                    pub fn new(task_priority: u16) -> Self {
                        Self { task_priority }
                    }
                }

                #cfg_core
                impl #mutex_ty for #proxy_name {
                    type ResourceType = #element_ty;
                    #impl_lock_fn
                }
            }
        });
        quote! {
            #(#proxies)*
        }
    }

    pub fn generate_shared_for_task(&self, task: &RticTask) -> TokenStream2 {
        let cfg_core = multibin::multibin_cfg_core(self.args.core);
        let task_resources_idents = &task.args.shared_idents;
        if task_resources_idents.is_empty() {
            return quote!();
        }

        // generate `field_name : proxy_type` to use for populating struct body
        let field_and_proxytype = task_resources_idents.iter().filter_map(|resource_ident| {
            if let Some(resource) = self.get_field(resource_ident) {
                let ident = &resource.ident;
                let proxy_type = utils::get_proxy_name(ident);
                Some(quote! {#ident: #proxy_type})
            } else {
                None
            }
        });
        let field_and_proxytype2 = field_and_proxytype.clone();

        // TODO: replace `shared(&self)` with individual `shared_resource_name(&self) -> proxy_type`
        // to avoid constructing the whole shared structure only for one resource access.

        let task_ty = task.name();
        let task_prio = task.args.priority;
        let task_shared_resources_struct =
            format_ident!("__{}_shared_resources", task.name_snakecase());
        quote! {
            // Shared resources access through shared() API for `#task_ty`
            #cfg_core
            impl #task_ty {
                pub fn shared(&self) -> #task_shared_resources_struct {
                    const TASK_PRIORITY: u16 = #task_prio;
                    #task_shared_resources_struct::new(TASK_PRIORITY)
                }
            }

            // internal struct for `#task_ty` resource proxies
            #cfg_core
            pub struct #task_shared_resources_struct {
                #(pub #field_and_proxytype ,)*
            }

            #cfg_core
            impl #task_shared_resources_struct {
                #[inline(always)]
                pub fn new(priority: u16) -> Self {
                    Self {
                        #(#field_and_proxytype2::new(priority) ,)*
                    }
                }
            }

        }
    }
}

pub mod utils {
    use quote::format_ident;

    #[inline(always)]
    pub fn get_proxy_name(ident: &syn::Ident) -> syn::Ident {
        format_ident!("__{ident}_mutex")
    }
}