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// }