voidio 0.1.14

VOID I/O - High-performance Cross-platform I/O for Rust.
use std::{net::SocketAddr, sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, mpsc::Sender, Arc}};

use crate::net::*;

#[macro_export]
macro_rules! dprintln {
    ($self:expr, $fmt:literal $(, $args:expr)* $(,)?) => {
        if $self.debug_mode {
            println!($fmt $(, $args)*);
        }
    };
}

pub struct UdpServerThreadContext {
    pub(crate) id: usize,
    pub(crate) name: String,
    pub(crate) server_address: SocketAddr,
    pub(crate) server_running: Arc<AtomicBool>,
    pub(crate) debug_mode: bool,
    pub(crate) socket: Socket,
    pub(crate) c: usize,
    pub(crate) processed_counter: Arc<AtomicUsize>,
    pub(crate) datagram_handler: Option<Box<dyn FnMut(SocketAddr, &mut [u8]) + Send + Sync + 'static>>,
    pub(crate) kernel_mode: bool,
    pub(crate) ready_tx: Sender<()>,
}

impl UdpServerThreadContext {
    pub fn new(socket: Socket, server_address: SocketAddr, ready_tx: Sender<()>) -> Self {
        Self {
            id: 0,
            name: format!("UdpServerThreadContext-X"),
            server_address,
            socket,
            server_running: Arc::new(AtomicBool::new(false)),
            debug_mode: false,
            c: 0,
            processed_counter: Arc::new(AtomicUsize::new(0)),
            datagram_handler: None,
            kernel_mode: false,
            ready_tx
        }
    }

    #[inline(always)]
    pub fn pop(&mut self, buf: &mut [u8], len: &mut usize) -> std::io::Result<SocketAddr> {
        if self.c % 100_000 == 0 {
            self.processed_counter.fetch_add(self.c, Ordering::Relaxed);
            self.c = 0;
        }
        self.socket.popmsg(buf, len, 0)
    }

    #[inline(always)]
    pub fn send(&self, buf: &[u8], addr: &SocketAddr) -> std::io::Result<usize> {
        self.socket.send_to(buf, addr, 0)
    }

    pub fn on_datagram<F>(&mut self, h: F)
    where
        F: FnMut(SocketAddr, &mut [u8]) + Send + Sync + 'static,
    {
        self.datagram_handler = Some(Box::new(h));
    }

    pub fn make_ready(&self) {
        self.ready_tx.send(()).expect("Failed to send ready signal");
        while !self.server_running.load(Ordering::Relaxed) {
            std::thread::yield_now();
        }
    }

    pub fn run(&mut self) -> std::io::Result<()> {
        if self.kernel_mode {
            self.begin_raw_queue_poll_loop()
        } else {
            #[cfg(unix)] {
                self.begin_popmany_loop()
            }
            #[cfg(not(unix))] {
                self.begin_pop_loop()
            }
        }
    }
}