rtipc 0.9.0

Real-Time IPC, based on a zero-copy, wait-free circular message queue implementation
Documentation
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::thread::JoinHandle;
use std::time;
use std::time::Duration;

use nix::errno::Errno;

use rtipc::ChannelGroup;
use rtipc::Consumer;
use rtipc::PopResult;
use rtipc::Producer;
use rtipc::client_connect;

use crate::common::CommandArgs;
use crate::common::CommandId;
use crate::common::DivArgs;
use crate::common::MsgCommand;
use crate::common::MsgEvent;
use crate::common::MsgResponse;
use crate::common::SendEventArgs;
use crate::common::rpc::CLIENT_GROUP_RPC_CREATE;
use crate::common::wait_pollin;

mod common;

static STOP_EVENT_LISTERNER: AtomicBool = AtomicBool::new(false);

fn handle_events(mut consumer: Consumer<MsgEvent>) -> Result<(), Errno> {
    while !STOP_EVENT_LISTERNER.load(Ordering::Relaxed) {
        let eventfd = consumer.eventfd().unwrap();
        let ev = wait_pollin(eventfd, Duration::from_millis(10))?;

        if !ev {
            continue;
        }

        match consumer.pop().unwrap() {
            PopResult::NoMessage => return Err(Errno::EBADMSG),
            PopResult::NoNewMessage => return Err(Errno::EBADMSG),
            PopResult::Success => {
                let msg = consumer.current_message().unwrap();
                println!("client received event: id = {} nr = {}", msg.id, msg.nr)
            }
            PopResult::SuccessMessagesDiscarded => {
                let msg = consumer.current_message().unwrap();
                println!("client received event: id = {} nr = {}", msg.id, msg.nr)
            }
        };
    }
    println!("handle_events returns");
    Ok(())
}

struct App {
    command: Producer<MsgCommand>,
    response: Consumer<MsgResponse>,
    event_listener: Option<JoinHandle<Result<(), Errno>>>,
}

impl App {
    pub fn new(mut grp: ChannelGroup) -> Self {
        let command = grp.acquire_producer(0).unwrap();
        let response = grp.acquire_consumer(0).unwrap();
        let event = grp.acquire_consumer(1).unwrap();

        let event_listener = Some(thread::spawn(move || handle_events(event)));

        Self {
            command,
            response,
            event_listener,
        }
    }

    pub fn run(&mut self, cmds: &[MsgCommand]) {
        let pause = time::Duration::from_millis(10);

        for cmd in cmds {
            self.command.current_message().clone_from(cmd);
            self.command.force_push().unwrap();

            loop {
                match self.response.pop().unwrap() {
                    PopResult::NoMessage => {
                        thread::sleep(pause);
                        continue;
                    }
                    PopResult::NoNewMessage => {
                        thread::sleep(pause);
                        continue;
                    }
                    PopResult::Success => {}
                    PopResult::SuccessMessagesDiscarded => {}
                };
                let msg = self.response.current_message().unwrap();
                println!(
                    "client received response id = {}, result = {} ",
                    msg.id, msg.result
                );
                break;
            }
        }
        thread::sleep(time::Duration::from_millis(100));
        STOP_EVENT_LISTERNER.store(true, Ordering::Relaxed);
        self.event_listener.take().map(|h| h.join());
    }
}

fn main() {
    let commands: [MsgCommand; 6] = [
        MsgCommand {
            id: CommandId::Hello as u32,
            args: unsafe { std::mem::zeroed() },
        },
        MsgCommand {
            id: CommandId::SendEvent as u32,
            args: CommandArgs {
                send: SendEventArgs {
                    id: 11,
                    force: false,
                    num: 20,
                },
            },
        },
        MsgCommand {
            id: CommandId::SendEvent as u32,
            args: CommandArgs {
                send: SendEventArgs {
                    id: 12,
                    force: true,
                    num: 20,
                },
            },
        },
        MsgCommand {
            id: CommandId::Div as u32,
            args: CommandArgs {
                div: DivArgs {
                    divisor: 100.0,
                    divident: 7.0,
                },
            },
        },
        MsgCommand {
            id: CommandId::Div as u32,
            args: CommandArgs {
                div: DivArgs {
                    divisor: 100.0,
                    divident: 0.0,
                },
            },
        },
        MsgCommand {
            id: CommandId::Stop as u32,
            args: unsafe { std::mem::zeroed() },
        },
    ];

    let attr = &CLIENT_GROUP_RPC_CREATE;
    let grp = client_connect("rtipc.sock", attr).unwrap();
    let mut app = App::new(grp);
    thread::sleep(time::Duration::from_millis(100));
    app.run(&commands);
}