cfun 0.2.11

Tidy up common functions
Documentation
#[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),
}

/// Lock-Free Map
#[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,
{
    /// create new CtlConns
    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 }
    }

    /// insert new value
    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
    }

    /// insert new value
    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
    }

    /// remove key
    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()));
}