#[cfg(feature = "net")]
use std::{collections::HashMap, fmt::Debug};
#[cfg(feature = "net")]
use tokio::sync::{
mpsc::{unbounded_channel, UnboundedSender},
oneshot,
};
#[derive(Debug)]
#[cfg(feature = "net")]
enum MapOpt<K, V>
where
K: 'static + Eq + std::hash::Hash + Clone + Send,
V: 'static + Clone + Send + Debug,
{
Insert(oneshot::Sender<Option<V>>, K, V),
Get(oneshot::Sender<Option<V>>, K),
Remove(oneshot::Sender<Option<V>>, K),
}
#[derive(Debug)]
#[cfg(feature = "net")]
pub struct LFMap<K, V>
where
K: 'static + Eq + std::hash::Hash + Clone + Send,
V: 'static + Clone + Send + Debug,
{
opt_sender: UnboundedSender<MapOpt<K, V>>,
}
#[cfg(feature = "net")]
impl<K, V> LFMap<K, V>
where
K: 'static + Eq + std::hash::Hash + Clone + Send,
V: 'static + Clone + Send + Debug,
{
pub fn new() -> Self {
let (opt_sender, mut opt_receiver) = unbounded_channel::<MapOpt<K, V>>();
tokio::spawn(async move {
let mut tcp_pool: HashMap<K, V> = HashMap::new();
while let Some(opt) = opt_receiver.recv().await {
match opt {
MapOpt::Insert(sender, key, value) => {
let ret = tcp_pool.insert(key, value);
sender.send(ret).unwrap();
}
MapOpt::Remove(sender, port) => {
let ret = tcp_pool.remove(&port);
sender.send(ret).unwrap();
}
MapOpt::Get(sender, key) => {
let tcp_stream = tcp_pool.get(&key);
if let Some(links) = tcp_stream {
sender.send(Some(links.clone())).unwrap();
} else {
sender.send(None).unwrap();
}
}
}
}
});
Self { opt_sender }
}
pub async fn insert(&self, key: K, value: V) -> Option<V> {
let (sender, receiver) = oneshot::channel();
self.opt_sender
.send(MapOpt::Insert(sender, key, value))
.unwrap();
let data = receiver.await.unwrap();
data
}
pub async fn get(&self, key: K) -> Option<V> {
let (sender, receiver) = oneshot::channel();
self.opt_sender.send(MapOpt::Get(sender, key)).unwrap();
let data = receiver.await.unwrap();
data
}
pub async fn remove(&self, key: K) -> Option<V> {
let (sender, receiver) = oneshot::channel();
self.opt_sender.send(MapOpt::Remove(sender, key)).unwrap();
let data = receiver.await.unwrap();
data
}
}
#[cfg(feature = "net")]
#[tokio::test]
async fn test_lfmap() {
let map = LFMap::new();
map.insert("key1".to_string(), "value1".to_string()).await;
let value = map.get("key1".to_string()).await;
assert_eq!(value, Some("value1".to_string()));
let value = map.remove("key1".to_string()).await;
assert_eq!(value, Some("value1".to_string()));
}