makepad-platform 0.3.0

Makepad platform layer
use {
    std::sync::{
        mpsc::{
            channel,
            Sender,
            Receiver,
            RecvError,
            TryRecvError,
            SendError,
        },
        Arc,
        Mutex
    },
    crate::{
        makepad_live_id::LiveId,
        cx::Cx,
        cx_api::*,
        event::{Signal, Event}
    }
};

pub struct ToUIReceiver<T> {
    sender: Sender<T>,
    pub receiver: Receiver<T>,
    signal: Signal
}

pub struct ToUISender<T> {
    sender: Sender<T>,
    signal: Signal
}

impl<T> Clone for ToUISender<T> {
    fn clone(&self) -> Self {
        Self {sender: self.sender.clone(), signal: self.signal.clone()}
    }
}

unsafe impl<T> Send for ToUISender<T> {}

impl<T> Default for ToUIReceiver<T> {
    fn default() -> Self {
        let (sender, receiver) = channel();
        Self {
            sender,
            receiver,
            signal: LiveId::unique().into()
        }
    }
}

impl<T> ToUIReceiver<T> {
    pub fn sender(&self) -> ToUISender<T> {
        ToUISender {
            sender: self.sender.clone(),
            signal: self.signal.clone()
        }
    }
    
    
    pub fn try_recv(&self, event: &Event) -> Result<T, TryRecvError> {
        if let Event::Signal(se) = event {
            if se.signals.get(&self.signal).is_some() {
                return self.receiver.try_recv()
            }
        }
        Err(TryRecvError::Empty)
    }
}

impl<T> ToUISender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T >> {
        let res = self.sender.send(t);
        Cx::post_signal(self.signal);
        res
    }
}

pub struct FromUIReceiver<T> {
    receiver: Receiver<T>,
}

pub struct FromUISender<T> {
    receiver: Option<Receiver<T >>,
    sender: Sender<T>,
}

unsafe impl<T> Send for FromUIReceiver<T> {}

impl<T> Default for FromUISender<T> {
    fn default() -> Self {
        let (sender, receiver) = channel();
        Self {
            sender,
            receiver: Some(receiver),
        }
    }
}

impl<T> FromUISender<T> {
    pub fn new_channel(&mut self) {
        let (sender, receiver) = channel();
        self.sender = sender;
        self.receiver = Some(receiver)
    }
    
    pub fn send(&self, t: T) -> Result<(), SendError<T >> {
        self.sender.send(t)
    }
    
    pub fn sender(&self) -> FromUISender<T> {
        FromUISender {
            sender: self.sender.clone(),
            receiver: None
        }
    }
    
    pub fn receiver(&mut self) -> FromUIReceiver<T> {
        FromUIReceiver {
            receiver: self.receiver.take().unwrap()
        }
    }
}

impl<T> FromUIReceiver<T> {
    pub fn recv(&self) -> Result<T, RecvError> {
        self.receiver.recv()
    }
    
    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        self.receiver.try_recv()
    }
}

pub struct ThreadPool<T: Clone + Send + 'static> {
    sender: Sender<Box<dyn FnOnce(Option<T>) + Send + 'static>>,
    msg_senders: Vec<Sender<T>>
}

impl<T> ThreadPool<T> where T : Clone + Send + 'static{
    pub fn new(cx: &mut Cx, num_threads: usize) -> Self {
        let (sender, receiver) = channel::<Box<dyn FnOnce(Option<T>) + Send + 'static>>();
        let receiver = Arc::new(Mutex::new(receiver));
        let mut msg_senders = Vec::new();
        for _ in 0..num_threads {
            let receiver = receiver.clone();
            let (msg_send, msg_recv) = channel::<T>();
            msg_senders.push(msg_send);
            cx.spawn_thread(move || loop {
                let task = if let Ok(receiver) = receiver.lock() {
                    match receiver.recv() {
                        Ok(task) => task,
                        Err(_) => return
                    }
                }
                else {
                    panic!();
                };
                let mut msg_out = None;
                while let Ok(msg) = msg_recv.try_recv(){
                    msg_out = Some(msg);
                }
                task(msg_out);
            })
        }
        Self{
            sender,
            msg_senders
        }
    }
    
    pub fn send_msg(&self, msg: T){
        for sender in &self.msg_senders{
            sender.send(msg.clone()).unwrap();
        }
    }
    
    pub fn execute<F>(&self, task: F) where F: FnOnce(Option<T>) + Send + 'static {
        self.sender.send(Box::new(task)).unwrap();
    }
}