Rust code: demo of message system

Requirements:

  1. Multi-threads receive/send messages

  2. Use mailbox ID to find message channel

Implementation:

  1. use mpsc lib for message channel

  2. use hash table for ID to message channel mapping

Limitation:

  1. mpsc channel has sender and receiver, but only sender could be clone() in rust. So only sender could be saved in hash table. refer to limitation 2.

  2. To share hash table among tasks, need Arc and Mutex for hash table. But the lock range impacts sender's function. To make multi-tasks can work at the same time( not need wait for one task finishing all job then release lock), we need drop the lock of hash table. And only sender could support this drop.

Code:

  1. message_lib.rs
rust 复制代码
use once_cell::sync::Lazy;

use std::vec::Vec;
use std::collections::HashMap;
use std::sync::{Arc, Mutex, mpsc};
//use std::thread;
//use std::time::Duration;


pub struct MessageHeader{
    pub src_id: u32,
    pub dest_id: u32,
    pub primitive: u32,
    pub param: Vec<u32>,
}

// Define a struct to hold the senders with IDs
pub struct MailboxRegistry {
    senders: HashMap<u32, mpsc::Sender<MessageHeader>>,
}

impl MailboxRegistry {
    pub fn new() -> Self {
        MailboxRegistry {
            senders: HashMap::new(),
        }
    }

    pub fn add_mailbox(&mut self, id: u32, sender: mpsc::Sender<MessageHeader>) {
        self.senders.insert(id, sender);
    }

    pub fn get_mailbox_sender(&self, id: u32) -> Option<&mpsc::Sender<MessageHeader>> {
        self.senders.get(&id)
    }
}

pub static MAILBOX_MATRIX: Lazy<Arc<Mutex<MailboxRegistry>>> = Lazy::new(|| {
    Arc::new(Mutex::new(MailboxRegistry::new()))
});

pub struct MailboxSystem {
    //pub ch_matrix : MailboxRegistry,
}

impl MailboxSystem {

    pub fn create_mailbox_channel(id: u32) -> mpsc::Receiver<MessageHeader> {
        let (sender, receiver) = mpsc::channel();
        {
            MAILBOX_MATRIX.lock().unwrap().add_mailbox(id, sender);
        }
        println!("Created channel ID {}", id);
        return receiver;
    }

    pub fn mb_send_message(id:u32, msg:MessageHeader)
    {
        println!("try to send message from sender ID {}, trying to get lock()", id);
        let mailbox_registry = MAILBOX_MATRIX.lock().unwrap();
        if let Some(sender) = mailbox_registry.get_mailbox_sender(id) { //self.get_mailbox_channel_sender(id) {
            /*unlock MAILBOX_MATRIX here*/
            let sender_ref = sender.clone();
            drop(mailbox_registry);
            /*then send message*/
            sender_ref.send(msg).unwrap();
            println!("Sent message from sender ID {}", id);
        } else {
            println!("No sender found for ID {}", id);
        }
    }

}

pub fn print_message(msg:&MessageHeader)
{
    println!("messge src {}",msg.src_id);
    println!("messge dest {}",msg.dest_id);
    println!("messge primitive {}",msg.primitive);
    for element in &(msg.param) {
        println!("Element: {}", element);
    }
}
  1. main.rs
rust 复制代码
use std::vec::Vec;
use std::sync::{mpsc};
use std::thread;
use std::time::Duration;

mod message_lib;
use crate::message_lib::{MailboxSystem,MessageHeader,print_message};

pub fn thread_send_message(mailbox_id:u32, src_id:u32, dest_id:u32, primitive:u32)
{
    let mut msg = MessageHeader {
        src_id : src_id,
        dest_id : dest_id,
        primitive : primitive,
        param : Vec::new(),
    };
    msg.param.push(primitive*2);
    MailboxSystem::mb_send_message(mailbox_id, msg);
}
pub fn thread_recv_message(receiver:&mpsc::Receiver<MessageHeader>) -> u32
{
    match receiver.recv() {
        Ok(msg) => {
            print_message(&msg);
            return msg.primitive;
        }
        Err(_) => {
            println!("Receiver fail");
            return 0;
        }
    }
}

fn main() {
    let thread_recv = thread::spawn( move || {
            println!("start Receiver");
            let mut tx_1_done = 0;
            let mut tx_2_done = 0;
            let receiver = MailboxSystem::create_mailbox_channel(1);
            loop {
                let count = thread_recv_message(&receiver);
                if count == 9999 {
                    tx_1_done = 1;
                }
                if count == 8888 {
                    tx_2_done = 1;
                }
                if tx_1_done == 1 && tx_2_done == 1 {
                    break;
                }
            }
    });
    thread::sleep(Duration::from_secs(1));
    let thread_send1 = thread::spawn( move || {
        println!("start Sender1");
        let mailbox_id = 1;
        let mut primitive = 0;
        for _ in 0..500 {
            primitive += 1;
            thread_send_message(mailbox_id,8,9,primitive);
        }
        primitive = 9999;
        thread_send_message(mailbox_id,8,9,primitive);
        thread::sleep(Duration::from_secs(1));
    });
    let thread_send2 = thread::spawn( move || {
        println!("start Sender2");
        let mailbox_id = 1;
        let mut primitive = 500;
        for _ in 0..400 {
            primitive += 1;
            thread_send_message(mailbox_id,12,9,primitive);
        }
        primitive = 8888;

        thread_send_message(mailbox_id,8,9,primitive);
        thread::sleep(Duration::from_secs(1));
    });
    match thread_send1.join() {
        Ok(_) => println!("The send thread1 has finished."),
        Err(_) => println!("An error occurred while joining the thread"),
    }
    match thread_send2.join() {
        Ok(_) => println!("The send thread2 has finished."),
        Err(_) => println!("An error occurred while joining the thread"),
    }
    match thread_recv.join() {
        Ok(_) => println!("The recv thread has finished."),
        Err(_) => println!("An error occurred while joining the thread:"),
    }

}
  1. cargo.toml
rust 复制代码
[package]
name = "message"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
once_cell = "1.4.0"

[lib]
path = "src/message_lib.rs"
相关推荐
第九序言T4 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
龙亘川5 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人5 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
Raas1006 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
专注仿真6 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
jimy17 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
呆呆虫127 小时前
用 orjson 加速 SerpBase 响应解析:基准对比与注意事项
开发语言·php
心疼你的一切8 小时前
Python自动发邮件实战定时发报表
大数据·开发语言·python
Wang's Blog9 小时前
Java 项目实战:交友项目 - 用户体系集成总结
java·开发语言·交友
中科三方9 小时前
IPv6检测常见问题:AAAA记录检测不通过是什么原因?
开发语言·php