turbo_tasks/
registry.rs

1use std::{fmt::Debug, hash::Hash, num::NonZeroU64, ops::Deref};
2
3use dashmap::mapref::entry::Entry;
4use once_cell::sync::Lazy;
5
6use crate::{
7    FxDashMap, TraitType, ValueType,
8    id::{FunctionId, TraitTypeId, ValueTypeId},
9    id_factory::IdFactory,
10    native_function::NativeFunction,
11    no_move_vec::NoMoveVec,
12};
13
14static FUNCTION_ID_FACTORY: IdFactory<FunctionId> = IdFactory::new_const(
15    FunctionId::MIN.to_non_zero_u64(),
16    FunctionId::MAX.to_non_zero_u64(),
17);
18static FUNCTIONS_BY_NAME: Lazy<FxDashMap<&'static str, FunctionId>> = Lazy::new(FxDashMap::default);
19static FUNCTIONS_BY_VALUE: Lazy<FxDashMap<&'static NativeFunction, FunctionId>> =
20    Lazy::new(FxDashMap::default);
21static FUNCTIONS: Lazy<NoMoveVec<(&'static NativeFunction, &'static str)>> =
22    Lazy::new(NoMoveVec::new);
23
24static VALUE_TYPE_ID_FACTORY: IdFactory<ValueTypeId> = IdFactory::new_const(
25    ValueTypeId::MIN.to_non_zero_u64(),
26    ValueTypeId::MAX.to_non_zero_u64(),
27);
28static VALUE_TYPES_BY_NAME: Lazy<FxDashMap<&'static str, ValueTypeId>> =
29    Lazy::new(FxDashMap::default);
30static VALUE_TYPES_BY_VALUE: Lazy<FxDashMap<&'static ValueType, ValueTypeId>> =
31    Lazy::new(FxDashMap::default);
32static VALUE_TYPES: Lazy<NoMoveVec<(&'static ValueType, &'static str)>> = Lazy::new(NoMoveVec::new);
33
34static TRAIT_TYPE_ID_FACTORY: IdFactory<TraitTypeId> = IdFactory::new_const(
35    TraitTypeId::MIN.to_non_zero_u64(),
36    TraitTypeId::MAX.to_non_zero_u64(),
37);
38static TRAIT_TYPES_BY_NAME: Lazy<FxDashMap<&'static str, TraitTypeId>> =
39    Lazy::new(FxDashMap::default);
40static TRAIT_TYPES_BY_VALUE: Lazy<FxDashMap<&'static TraitType, TraitTypeId>> =
41    Lazy::new(FxDashMap::default);
42static TRAIT_TYPES: Lazy<NoMoveVec<(&'static TraitType, &'static str)>> = Lazy::new(NoMoveVec::new);
43
44fn register_thing<
45    K: Copy + Deref<Target = u32> + TryFrom<NonZeroU64>,
46    V: Copy + Hash + Eq,
47    const INITIAL_CAPACITY_BITS: u32,
48>(
49    global_name: &'static str,
50    value: V,
51    id_factory: &IdFactory<K>,
52    store: &NoMoveVec<(V, &'static str), INITIAL_CAPACITY_BITS>,
53    map_by_name: &FxDashMap<&'static str, K>,
54    map_by_value: &FxDashMap<V, K>,
55) {
56    if let Entry::Vacant(e) = map_by_value.entry(value) {
57        let new_id = id_factory.get();
58        // SAFETY: this is a fresh id
59        unsafe {
60            store.insert(*new_id as usize, (value, global_name));
61        }
62        map_by_name.insert(global_name, new_id);
63        e.insert(new_id);
64    }
65}
66
67fn get_thing_id<K, V>(value: V, map_by_value: &FxDashMap<V, K>) -> K
68where
69    V: Hash + Eq + Debug,
70    K: Clone,
71{
72    if let Some(id) = map_by_value.get(&value) {
73        id.clone()
74    } else {
75        panic!("Use of unregistered {value:?}");
76    }
77}
78
79pub fn register_function(global_name: &'static str, func: &'static NativeFunction) {
80    register_thing(
81        global_name,
82        func,
83        &FUNCTION_ID_FACTORY,
84        &FUNCTIONS,
85        &FUNCTIONS_BY_NAME,
86        &FUNCTIONS_BY_VALUE,
87    )
88}
89
90pub fn get_function_id(func: &'static NativeFunction) -> FunctionId {
91    get_thing_id(func, &FUNCTIONS_BY_VALUE)
92}
93
94pub fn get_function_id_by_global_name(global_name: &str) -> Option<FunctionId> {
95    FUNCTIONS_BY_NAME.get(global_name).map(|x| *x)
96}
97
98pub fn get_function(id: FunctionId) -> &'static NativeFunction {
99    FUNCTIONS.get(*id as usize).unwrap().0
100}
101
102pub fn get_function_global_name(id: FunctionId) -> &'static str {
103    FUNCTIONS.get(*id as usize).unwrap().1
104}
105
106pub fn register_value_type(global_name: &'static str, ty: &'static ValueType) {
107    register_thing(
108        global_name,
109        ty,
110        &VALUE_TYPE_ID_FACTORY,
111        &VALUE_TYPES,
112        &VALUE_TYPES_BY_NAME,
113        &VALUE_TYPES_BY_VALUE,
114    )
115}
116
117pub fn get_value_type_id(func: &'static ValueType) -> ValueTypeId {
118    get_thing_id(func, &VALUE_TYPES_BY_VALUE)
119}
120
121pub fn get_value_type_id_by_global_name(global_name: &str) -> Option<ValueTypeId> {
122    VALUE_TYPES_BY_NAME.get(global_name).map(|x| *x)
123}
124
125pub fn get_value_type(id: ValueTypeId) -> &'static ValueType {
126    VALUE_TYPES.get(*id as usize).unwrap().0
127}
128
129pub fn get_value_type_global_name(id: ValueTypeId) -> &'static str {
130    VALUE_TYPES.get(*id as usize).unwrap().1
131}
132
133pub fn register_trait_type(global_name: &'static str, ty: &'static TraitType) {
134    register_thing(
135        global_name,
136        ty,
137        &TRAIT_TYPE_ID_FACTORY,
138        &TRAIT_TYPES,
139        &TRAIT_TYPES_BY_NAME,
140        &TRAIT_TYPES_BY_VALUE,
141    )
142}
143
144pub fn get_trait_type_id(func: &'static TraitType) -> TraitTypeId {
145    get_thing_id(func, &TRAIT_TYPES_BY_VALUE)
146}
147
148pub fn get_trait_type_id_by_global_name(global_name: &str) -> Option<TraitTypeId> {
149    TRAIT_TYPES_BY_NAME.get(global_name).map(|x| *x)
150}
151
152pub fn get_trait(id: TraitTypeId) -> &'static TraitType {
153    TRAIT_TYPES.get(*id as usize).unwrap().0
154}
155
156pub fn get_trait_type_global_name(id: TraitTypeId) -> &'static str {
157    TRAIT_TYPES.get(*id as usize).unwrap().1
158}