Expand description
§XWOS RUST:消息队列
XWOS RUST的消息队列是仿照 std::sync::mpsc
编写的。可以有多个发送者,但只能有一个接收者。
XWOS RUST的消息队列是一个先进先进(FIFO)队列。
消息队列在创建时,需要指定一个类型 T
,发送和接收的数据只能是类型 T
的数据。
发送时,消息队列会通过 Box
将类型 T
的数据存入堆内存中。然后将 Box<T>
的裸指针发送到队列。
可以发送到尾端(入队 XwmqTx::eq()
),也可将消息发送到队列的首端(插队 XwmqTx::jq()
)。
接收时,会从队列中取出 T
的裸指针,然后恢复成 Box<T>
后返回,由于 Box
能自动释放内存,因此用户不需要关心内存释放的问题。
接收消息可以从首端接收,也可以从尾端接收。
§创建
XWOS RUST的消息队列可使用 Xwmq::new()
创建。创建时需要指定两个类型参数:发送消息槽的个数以及消息数据的类型。
- 可以创建具有静态生命周期
static
约束的全局变量:
use xwrust::xwmd::xwmq::*;
static MQ: Xwmq<16, String> = Xwmq::new(); // 16个消息槽,数据类型为String
- 也可以使用
alloc::sync::Arc
在heap中创建:
extern crate alloc;
use alloc::sync::Arc;
use xwrust::xwmd::xwmq::*;
pub fn xwrust_example_xwmq() {
let mq: Arc<Xwmq<16, String>> = Arc::new(Xwmq::new()); // 16个消息槽,数据类型为 `String`
}
§初始化
无论以何种方式创建的消息队列,都必须在使用前调用 Xwmq::init()
进行初始化,
初始化后会返回消息队列的发送者 XwmqTx
以及接收者 XwmqRx
。
pub fn xwrust_example_xwmq() {
let (tx, rx) = MQ.init();
}
§发送
Xwmq
的发送者 XwmqTx
具有 Send
约束,可在线程之间转移所有权,但不能在线程之间共享( !Sync
)。
发送者 XwmqTx
可被 XwmqTx::clone()
为多个发送者,由不同线程持有,向接收者 XwmqRx
发送消息。
§入队
入队 方式是将消息发送到队列的 尾端 , 入队 时,会通过 Box
将数据放入heap中,然后进行发送。
§等待入队
方法 XwmqTx::eq()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
- 当线程阻塞等待被中断时,返回
XwmqError::Interrupt
。
§超时等待入队
方法 XwmqTx::eq_to()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
- 当线程阻塞等待被中断时,返回
XwmqError::Interrupt
。 - 当到达指定的唤醒时间点,线程被唤醒,并返回
XwmqError::Timedout
。
§等待入队,且等待不可不中断
方法 XwmqTx::eq_unintr()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
- 发送线程的阻塞等待不可被中断。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
§尝试等待入队
方法 XwmqTx::tryeq()
方法可在 任意 上下文中使用,不会阻塞,只会检测信号量的值:
- 当消息队列中没有可用的消息槽可用时,立即返回
XwmqError::NoSlot
。 - 当消息队列中有可用的消息槽时,发送线程会取走一个消息槽,并发送数据。
§插队
插队 方式是将消息发送到队列的 首端 , 插队 时,会通过 Box
将数据放入heap中,然后进行发送。
§等待插队
方法 XwmqTx::jq()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
- 当线程阻塞等待被中断时,返回
XwmqError::Interrupt
。
§超时等待插队
方法 XwmqTx::jq_to()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
- 当线程阻塞等待被中断时,返回
XwmqError::Interrupt
。 - 当到达指定的唤醒时间点,线程被唤醒,并返回
XwmqError::Timedout
。
方法 XwmqTx::jq_unintr()
只可在 线程 上下文中使用:
- 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
- 发送线程的阻塞等待不可被中断。
- 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
§尝试等待插队
方法 XwmqTx::tryjq()
方法可在 任意 上下文中使用,不会阻塞,只会检测信号量的值:
- 当消息队列中没有可用的消息槽可用时,立即返回
XwmqError::NoSlot
。 - 当消息队列中有可用的消息槽时,发送线程会取走一个消息槽,并发送数据。
§接收
Xwmq
的接收者 XwmqRx
具有 Send
约束,可在线程之间转移所有权,但不能在线程之间共享( !Sync
)。
接收者 XwmqRx
不可被 ”克隆“,因为接收者只能有一个。
接收消息后,会释放消息槽。若有发送线程正在等待消息槽,将唤醒发送线程。
§首端离队
从消息队列的 首端 取出消息,称为 首端离队 。
接收成功,消息 离队 时,会通过 Box::from_raw()
将数据重新放入 Box
中,然后通过 Ok()
返回。
当 Box
被 drop()
时,会自动释放heap内存。
§等待离队
方法 XwmqRx::dq()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
- 当线程阻塞等待被中断时,通过
Err()
返回XwmqError::Interrupt
。
§超时等待离队
方法 XwmqRx::dq_to()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
- 当线程阻塞等待被中断时,通过
Err()
返回XwmqError::Interrupt
。 - 当到达指定的唤醒时间点,线程被唤醒,并通过
Err()
返回XwmqError::Timedout
。
方法 XwmqRx::dq_unintr()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待。
- 接收线程的阻塞等待不可被中断。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
§尝试等待离队
方法 XwmqRx::trydq()
方法可在 任意 上下文中使用,不会阻塞,只会检测信号量的值:
- 当消息队列中没有消息时,立即通过
Err()
返回XwmqError::NoMsg
。 - 当消息队列中有可用的消息时,接收线程会取走一个消息,并释放消息槽。
§尾端离队
从消息队列的 尾端 取出消息,称为 尾端离队 。
接收成功,消息 离队 时,会通过 Box::from_raw()
将数据重新放入 Box
中,
然后通过 Ok()
返回。
当 Box
被 drop()
时,会自动释放heap内存。
§等待反向离队
方法 XwmqRx::rq()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
- 当线程阻塞等待被中断时,通过
Err()
返回XwmqError::Interrupt
。
§超时等待反向离队
方法 XwmqRx::rq_to()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
- 当线程阻塞等待被中断时,通过
Err()
返回XwmqError::Interrupt
。 - 当到达指定的唤醒时间点,线程被唤醒,并通过
Err()
返回XwmqError::Timedout
。
方法 XwmqRx::rq_unintr()
只可在 线程 上下文中使用:
- 当消息队列中没有消息时,接收线程会阻塞等待。
- 接收线程的阻塞等待不可被中断。
- 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
§尝试等待反向离队
方法 XwmqRx::tryrq()
方法可在 任意 上下文中使用,不会阻塞,只会检测信号量的值:
- 当消息队列中没有消息时,立即通过
Err()
返回XwmqError::NoMsg
。 - 当消息队列中有可用的消息时,接收线程会取走一个消息,并释放消息槽。
§示例
XWOS/xwam/xwrust-example/xwrust_example_xwmq
§对比 std::sync::mpsc
- XWOS RUST:
#![no_std]
extern crate alloc;
use xwrust::xwos::thd;
use xwrust::xwmd::xwmq::*;
static MQ: Xwmq<16, u32> = Xwmq::new();
pub fn xwrust_example_xwmq() {
println!("XWOS RUST Example: XWMQ");
let (tx, rx) = MQ.init();
let _ = thd::Builder::new()
.spawn(move |_| { // 子线程闭包
tx.eq(53);
"OK"
});
let rc = rx.dq();
match rc {
Ok(d) => { // d为接收到的数据,并被放在智能指针Box中
},
Err(e) => {
},
};
}
use std::thread;
use std::sync::mpsc::sync_channel;
let (tx, rx) = sync_channel::<i32>(0);
thread::spawn(move|| {
tx.send(53).unwrap();
});
rx.recv().unwrap();
§构建全局变量的方式
std::sync::mpsc
没有编译期构造函数,因此只能借助 宏lazy_static!
创建全局变量;xwrust::xwmd::xwmq
则可以直接在函数外部定义。
§通道类型
std::sync::mpsc
还有异步的通道std::sync::mpsc::channel()
;xwrust::xwmd::xwmq
通过Xwmq::init()
返回的是类似于std::sync::mpsc::sync_channel()
的通道,xwrust::xwmd::xwmq
没有异步的通道 。
§接收消息返回方式不同
std::sync::mpsc
接收到消息后,直接返回类型为 T 的消息;xwrust::xwmd::xwmq
则返回Box<T>
。
Structs§
- 消息队列对象结构体
Enums§
- 消息队列的错误码
Constants§
- 消息队列对象占用的内存大小
- 消息占用的内存大小