synthphonia/forward/data/
all_eq.rs

1use std::{
2    cell::UnsafeCell,
3    collections::hash_map,
4    task::Poll, ops::Index,
5};
6
7use derive_more::{Constructor, Deref, From, Into, TryInto};
8use futures::Future;
9use simple_rc_async::sync::broadcast::MaybeReady;
10
11use crate::{
12    galloc::AllocForAny,
13    expr::Expr,
14    utils::UnsafeCellExt,
15    value::Value, log, info, debg,
16};
17use ahash::AHashMap as HashMap;
18
19#[derive(From, Deref)]
20/// A Term Dispatcher for Equal
21pub struct Data(UnsafeCell<HashMap<Value, MaybeReady<&'static Expr>>>);
22
23impl Default for Data {
24    /// Creates a new instance using the default initialization, which internally delegates to the new method.
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl Data {
31    /// Creates and returns a new instance of the data structure by initializing it with an empty hash map. 
32    pub fn new() -> Self { Self(HashMap::new().into()) }
33
34    #[inline(always)]
35    /// Return the number of entries stored in the underlying container. 
36    pub fn count(&self) -> usize { unsafe{self.as_mut().len()} }
37
38    #[inline(always)]
39    /// Updates the mapping by setting an associated expression for a given value and returns the updated expression when modifications are made.
40    pub fn set(&self, v: Value, e: Expr) -> Option<&'static Expr> {
41        match unsafe{ self.as_mut().entry(v) } {
42            hash_map::Entry::Occupied(mut p) => {
43                if p.get().is_ready() {
44                    None
45                } else {
46                    let e = e.galloc();
47                    p.get_mut().set(e);
48                    Some(e)
49                }
50            }
51            hash_map::Entry::Vacant(v) => {
52                let e = e.galloc();
53                v.insert(MaybeReady::Ready(e));
54                Some(e)
55            }
56        }
57    }
58
59    #[inline(always)]
60    /// Sets the internal mapping for a given key with a new static expression value, and if necessary, triggers a notification to propagate the update. 
61    pub fn set_ref(&self, v: Value, e: &'static Expr) {
62        let mut sd = None;
63        match unsafe{ self.as_mut().entry(v) } {
64            hash_map::Entry::Occupied(mut p) => {
65                if !p.get().is_ready() { sd = p.get_mut().sender(e); }
66            }
67            hash_map::Entry::Vacant(v) => {
68                v.insert(MaybeReady::Ready(e));
69            }
70        }
71        if let Some(x) = sd { x.send(e) }
72    }
73
74    #[inline(always)]
75    /// Acquires asynchronously an expression for a given value, waiting for its readiness if necessary.
76    pub async fn acquire(&self, v: Value) -> &'static Expr {
77        match unsafe{ self.as_mut().entry(v) } {
78            hash_map::Entry::Occupied(o) => o.get().get().await,
79            hash_map::Entry::Vacant(v) => v.insert(MaybeReady::pending()).get().await,
80        }
81    }
82
83    #[inline(always)]
84    /// Checks whether the synthesis term associated with the provided value is still pending. 
85    pub fn is_pending(&self, v: Value) -> bool {
86        if let Some(a) = unsafe{ self.as_mut().get(&v) } {
87            !a.is_ready()
88        } else {
89            false
90        }
91    }
92
93    #[inline(always)]
94    /// Checks whether the underlying data structure contains the specified key. 
95    pub fn contains(&self, v: Value) -> bool {
96        match unsafe{ self.as_mut().entry(v) } {
97            hash_map::Entry::Occupied(o) => true,
98            hash_map::Entry::Vacant(v) => false,
99        }
100    }
101    // #[inline(always)]
102    // pub fn try_acquire(&self, v: Value) -> Option<EventBusRc<&'static Expr>> {
103    //     match unsafe{ self.as_mut().entry(v) } {
104    //         hash_map::Entry::Occupied(o) => {
105    //             match o.get() {
106    //                 DataStatus::Event(e) if !e.is_ready() => Some(e.clone()),
107    //                 _ => None
108    //             }
109    //         }
110    //         hash_map::Entry::Vacant(v) => {
111    //             let ev = EventBusRc::new();
112    //             v.insert(ev.clone().into());
113    //             Some(ev)
114    //         }
115    //     }
116    // }
117    /// Retrieves an expression reference from the underlying data structure based on a given index. 
118    pub fn at(&self, index: Value) -> Option<&'static Expr> {
119        unsafe{ &self.as_mut().get(&index) }.and_then(|x| {
120            x.poll_opt()
121        })
122    }
123    /// Retrieves a static expression reference corresponding to the provided value by performing an internal lookup. 
124    pub fn get(&self, index: Value) -> &'static Expr {
125        self.at(index).expect("No such entry")
126    }
127}
128
129// thread_local!{
130//     static DATA : UnsafeCell<HashMap<Value, DataStatus>> = HashMap::new().into();
131// }
132
133// #[inline(always)]
134// pub fn set(v: Value, e: Expr) -> bool {
135//     DATA.with(|data|{
136//         match unsafe { data.as_mut().entry(v)} {
137//             hash_map::Entry::Occupied(o) => {
138//                 o.get().try_notify(e)
139//             }
140//             hash_map::Entry::Vacant(v) => {
141//                 v.insert(e.galloc().into());
142//                 true
143//             }
144//         }
145//     })
146// }
147
148// #[inline(always)]
149// pub fn listen_to(v: Value) -> EventBusRc<&'static Expr> {
150//     DATA.with(|data|{
151//         match unsafe{ data.as_mut().entry(v) } {
152//             hash_map::Entry::Occupied(o) => o.get().try_add_task(),
153//             hash_map::Entry::Vacant(v) => {
154//                 let ev = EventBusRc::new_cur_task();
155//                 v.insert(ev.clone().into());
156//                 ev
157//             }
158//         }
159//     })
160// }