wasmrs_runtime/runtime/native/
mod.rs

1//! Native implementations of wasmrs-runtime functions and structs.
2#![allow(missing_docs)]
3use std::future::Future;
4use std::sync::Arc;
5
6use dashmap::DashMap;
7use parking_lot::Mutex;
8use tokio::task::JoinHandle;
9
10pub type TaskHandle = JoinHandle<()>;
11
12pub type BoxFuture<Output> = std::pin::Pin<Box<dyn Future<Output = Output> + Send + Sync + 'static>>;
13
14pub fn spawn<F>(id: &'static str, task: F) -> TaskHandle
15where
16  F: Future<Output = ()> + ConditionallySend,
17{
18  tracing::trace!("native:runtime:task:start:{}", id);
19  tokio::spawn(async move {
20    task.await;
21    tracing::trace!("native:runtime:task:end:{}", id);
22  })
23}
24
25pub fn exhaust_pool() {
26  unimplemented!("Not implemented in non-wasm hosts")
27}
28
29#[allow(missing_debug_implementations)]
30pub struct SafeMap<K, V>(DashMap<K, V>)
31where
32  K: std::hash::Hash,
33  K: Eq;
34
35impl<K, V> SafeMap<K, V>
36where
37  K: std::hash::Hash,
38  K: Eq,
39{
40  pub fn remove(&self, key: &K) -> Option<V> {
41    self.0.remove(key).map(|v| v.1)
42  }
43
44  pub fn insert(&self, key: K, value: V) {
45    self.0.insert(key, value);
46  }
47
48  #[must_use]
49  pub fn len(&self) -> usize {
50    self.0.len()
51  }
52
53  #[must_use]
54  pub fn is_empty(&self) -> bool {
55    self.0.is_empty()
56  }
57
58  pub fn cloned(&self, key: &K) -> Option<V>
59  where
60    V: Clone,
61  {
62    self.0.get(key).map(|v| v.clone())
63  }
64
65  pub fn entry(&self, key: K) -> Entry<'_, K, V> {
66    match self.0.entry(key) {
67      dashmap::mapref::entry::Entry::Occupied(v) => Entry::Occupied::<K, V>(OccupiedEntry(v)),
68      dashmap::mapref::entry::Entry::Vacant(v) => Entry::Vacant::<K, V>(VacantEntry(v)),
69    }
70  }
71}
72
73#[must_use]
74#[allow(missing_debug_implementations)]
75pub enum Entry<'a, K, V> {
76  Occupied(OccupiedEntry<'a, K, V>),
77  Vacant(VacantEntry<'a, K, V>),
78}
79
80#[allow(missing_debug_implementations)]
81pub struct OccupiedEntry<'a, K, V>(dashmap::mapref::entry::OccupiedEntry<'a, K, V>);
82
83impl<'a, K, V> OccupiedEntry<'a, K, V>
84where
85  K: Eq,
86  K: std::hash::Hash,
87{
88  pub fn get(&self) -> &V {
89    self.0.get()
90  }
91  pub fn remove(self) -> V {
92    self.0.remove()
93  }
94}
95
96#[allow(missing_debug_implementations)]
97pub struct VacantEntry<'a, K, V>(dashmap::mapref::entry::VacantEntry<'a, K, V>);
98
99impl<K, V> Default for SafeMap<K, V>
100where
101  K: std::hash::Hash,
102  K: Eq,
103{
104  fn default() -> Self {
105    Self(Default::default())
106  }
107}
108
109#[allow(missing_debug_implementations)]
110pub struct OptionalMut<T>(Arc<Mutex<Option<T>>>);
111
112impl<T> OptionalMut<T>
113where
114  T: Send,
115{
116  pub fn new(item: T) -> Self {
117    Self(Arc::new(Mutex::new(Some(item))))
118  }
119
120  #[must_use]
121  pub fn none() -> Self {
122    Self(Arc::new(Mutex::new(None)))
123  }
124
125  #[must_use]
126  pub fn take(&self) -> Option<T> {
127    self.0.lock().take()
128  }
129
130  pub fn insert(&self, item: T) {
131    let _ = self.0.lock().insert(item);
132  }
133
134  #[must_use]
135  pub fn is_some(&self) -> bool {
136    self.0.lock().is_some()
137  }
138
139  #[must_use]
140  pub fn is_none(&self) -> bool {
141    self.0.lock().is_none()
142  }
143}
144
145impl<T> Clone for OptionalMut<T> {
146  fn clone(&self) -> Self {
147    Self(self.0.clone())
148  }
149}
150
151#[allow(missing_debug_implementations)]
152pub struct MutRc<T>(pub(super) Arc<Mutex<T>>);
153
154impl<T> MutRc<T>
155where
156  T: ConditionallySendSync,
157{
158  pub fn new(item: T) -> Self {
159    Self(Arc::new(Mutex::new(item)))
160  }
161
162  pub fn lock(&self) -> parking_lot::lock_api::MutexGuard<'_, parking_lot::RawMutex, T> {
163    self.0.lock()
164  }
165}
166
167pub type RtRc<T> = Arc<T>;
168
169pub trait ConditionallySendSync: Send + Sync + 'static {}
170
171impl<S> ConditionallySendSync for S where S: Send + Sync + 'static {}
172
173pub trait ConditionallySend: Send + 'static {}
174
175impl<S> ConditionallySend for S where S: Send + 'static {}