#[macro_export]
macro_rules! define_cross_thread_type {
($type_name:ty) => {
$crate::paste::item! {
pub struct [<CrossThread $type_name>] {
id: u64
}
impl Default for [<CrossThread $type_name>] {
fn default() -> Self {
let id = $crate::fastrand::u64(..);
let mut inst = <$type_name>::default();
Self::map().write().insert(id, std::sync::Arc::new($crate::parking_lot::RwLock::new(inst)));
Self { id }
}
}
impl [<CrossThread $type_name>] {
fn map() -> &'static $crate::parking_lot::RwLock<std::collections::HashMap<u64, std::sync::Arc<$crate::parking_lot::RwLock<$type_name>>>> {
use std::{ collections::HashMap, sync::{ Arc, OnceLock } };
use $crate::parking_lot::RwLock;
static MAP: OnceLock<RwLock<HashMap<u64, Arc<RwLock<$type_name>>>>> = OnceLock::new();
MAP.get_or_init(|| RwLock::new(HashMap::new()))
}
pub fn get(&self) -> Option<std::sync::Arc<$crate::parking_lot::RwLock<$type_name>>> {
Some(Self::map().read().get(&self.id)?.clone())
}
pub fn clear_map() {
Self::map().write().clear();
}
}
impl $crate::serde::Serialize for [<CrossThread $type_name>] {
fn serialize<S: $crate::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use $crate::serde::ser::SerializeStruct;
let rwlock = self.get().ok_or($crate::serde::ser::Error::custom("Instance not found in static map"))?;
let mut state = serializer.serialize_struct(stringify!($type_name), 2)?;
state.serialize_field("id", &self.id)?;
state.serialize_field("data", &*rwlock.read())?;
state.end()
}
}
impl<'de> $crate::serde::Deserialize<'de> for [<CrossThread $type_name>] {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: $crate::serde::Deserializer<'de> {
#[derive($crate::serde::Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field { Id, Data }
struct HelperVisitor;
impl<'de> $crate::serde::de::Visitor<'de> for HelperVisitor {
type Value = [<CrossThread $type_name>];
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str(stringify!($type_name))
}
fn visit_seq<V>(self, mut seq: V) -> Result<[<CrossThread $type_name>], V::Error> where V: $crate::serde::de::SeqAccess<'de> {
let id: u64 = seq.next_element()?.ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
if [<CrossThread $type_name>]::map().read().contains_key(&id) {
return Ok([<CrossThread $type_name>] { id });
}
let data: $type_name = seq.next_element()?.ok_or_else(|| $crate::serde::de::Error::invalid_length(1, &self))?;
let mut map = [<CrossThread $type_name>]::map().write();
map.entry(id).or_insert_with(|| std::sync::Arc::new($crate::parking_lot::RwLock::new(data)));
Ok([<CrossThread $type_name>] { id })
}
fn visit_map<V>(self, mut map: V) -> Result<[<CrossThread $type_name>], V::Error> where V: serde::de::MapAccess<'de> {
let mut id = None;
let mut data = None;
while let Some(key) = map.next_key()? {
match key {
Field::Id => {
let _id = map.next_value()?;
if [<CrossThread $type_name>]::map().read().contains_key(&_id) {
return Ok([<CrossThread $type_name>] { id: _id });
}
id = Some(_id);
}
Field::Data => {
data = Some(map.next_value()?);
}
}
}
let id: u64 = id.ok_or_else(|| $crate::serde::de::Error::missing_field("id"))?;
let data: $type_name = data.ok_or_else(|| $crate::serde::de::Error::missing_field("data"))?;
let mut write_map = [<CrossThread $type_name>]::map().write();
write_map.entry(id).or_insert_with(|| std::sync::Arc::new($crate::parking_lot::RwLock::new(data)));
Ok([<CrossThread $type_name>] { id })
}
}
deserializer.deserialize_struct(stringify!($type_name), &["id", "data"], HelperVisitor)
}
}
}
}
}