xwrust/xwmd/xwmq.rs
1//! XWOS RUST:消息队列
2//! ========
3//!
4//! XWOS RUST的消息队列是仿照 [`std::sync::mpsc`] 编写的。可以有多个发送者,但只能有一个接收者。
5//!
6//! XWOS RUST的消息队列是一个先进先进(FIFO)队列。
7//!
8//! 消息队列在创建时,需要指定一个类型 `T` ,发送和接收的数据只能是类型 `T` 的数据。
9//! 发送时,消息队列会通过 [`Box`] 将类型 `T` 的数据存入堆内存中。然后将 `Box<T>` 的裸指针发送到队列。
10//! 可以发送到尾端(入队 [`XwmqTx::eq()`] ),也可将消息发送到队列的首端(插队 [`XwmqTx::jq()`] )。
11//!
12//! 接收时,会从队列中取出 `T` 的裸指针,然后恢复成 `Box<T>` 后返回,由于 [`Box`] 能自动释放内存,因此用户不需要关心内存释放的问题。
13//! 接收消息可以从首端接收,也可以从尾端接收。
14//!
15//!
16//! # 创建
17//!
18//! XWOS RUST的消息队列可使用 [`Xwmq::new()`] 创建。创建时需要指定两个类型参数:发送消息槽的个数以及消息数据的类型。
19//!
20//! + 可以创建具有静态生命周期 [`static`] 约束的全局变量:
21//!
22//! ```rust
23//! use xwrust::xwmd::xwmq::*;
24//!
25//! static MQ: Xwmq<16, String> = Xwmq::new(); // 16个消息槽,数据类型为String
26//! ```
27//!
28//! + 也可以使用 [`alloc::sync::Arc`] 在heap中创建:
29//!
30//! ```rust
31//! extern crate alloc;
32//! use alloc::sync::Arc;
33//!
34//! use xwrust::xwmd::xwmq::*;
35//!
36//! pub fn xwrust_example_xwmq() {
37//! let mq: Arc<Xwmq<16, String>> = Arc::new(Xwmq::new()); // 16个消息槽,数据类型为 `String`
38//! }
39//! ```
40//!
41//!
42//! # 初始化
43//!
44//! 无论以何种方式创建的消息队列,都必须在使用前调用 [`Xwmq::init()`] 进行初始化,
45//! 初始化后会返回消息队列的发送者 [`XwmqTx`] 以及接收者 [`XwmqRx`] 。
46//!
47//! ```rust
48//! pub fn xwrust_example_xwmq() {
49//! let (tx, rx) = MQ.init();
50//! }
51//! ```
52//!
53//!
54//! # 发送
55//!
56//! [`Xwmq`] 的发送者 [`XwmqTx`] 具有 [`Send`] 约束,可在线程之间转移所有权,但不能在线程之间共享( [`!Sync`] )。
57//!
58//! 发送者 [`XwmqTx`] 可被 [`XwmqTx::clone()`] 为多个发送者,由不同线程持有,向接收者 [`XwmqRx`] 发送消息。
59//!
60//! ## 入队
61//!
62//! **入队** 方式是将消息发送到队列的 **尾端** , **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
63//!
64//! ### 等待入队
65//!
66//! 方法 [`XwmqTx::eq()`] 只可在 **线程** 上下文中使用:
67//!
68//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
69//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
70//! + 当线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
71//!
72//! ### 超时等待入队
73//!
74//! 方法 [`XwmqTx::eq_to()`] 只可在 **线程** 上下文中使用:
75//!
76//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
77//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
78//! + 当线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
79//! + 当到达指定的唤醒时间点,线程被唤醒,并返回 [`XwmqError::Timedout`] 。
80//!
81//! ### 等待入队,且等待不可不中断
82//!
83//! 方法 [`XwmqTx::eq_unintr()`] 只可在 **线程** 上下文中使用:
84//!
85//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
86//! + 发送线程的阻塞等待不可被中断。
87//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
88//!
89//! ### 尝试等待入队
90//!
91//! 方法 [`XwmqTx::tryeq()`] 方法可在 **任意** 上下文中使用,不会阻塞,只会检测信号量的值:
92//!
93//! + 当消息队列中没有可用的消息槽可用时,立即返回 [`XwmqError::NoSlot`] 。
94//! + 当消息队列中有可用的消息槽时,发送线程会取走一个消息槽,并发送数据。
95//!
96//! ## 插队
97//!
98//! **插队** 方式是将消息发送到队列的 **首端** , **插队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
99//!
100//! ### 等待插队
101//!
102//! 方法 [`XwmqTx::jq()`] 只可在 **线程** 上下文中使用:
103//!
104//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
105//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
106//! + 当线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
107//!
108//! ### 超时等待插队
109//!
110//! 方法 [`XwmqTx::jq_to()`] 只可在 **线程** 上下文中使用:
111//!
112//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
113//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
114//! + 当线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
115//! + 当到达指定的唤醒时间点,线程被唤醒,并返回 [`XwmqError::Timedout`] 。
116//!
117//! 方法 [`XwmqTx::jq_unintr()`] 只可在 **线程** 上下文中使用:
118//!
119//! + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
120//! + 发送线程的阻塞等待不可被中断。
121//! + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,并发送数据。
122//!
123//! ### 尝试等待插队
124//!
125//! 方法 [`XwmqTx::tryjq()`] 方法可在 **任意** 上下文中使用,不会阻塞,只会检测信号量的值:
126//!
127//! + 当消息队列中没有可用的消息槽可用时,立即返回 [`XwmqError::NoSlot`] 。
128//! + 当消息队列中有可用的消息槽时,发送线程会取走一个消息槽,并发送数据。
129//!
130//!
131//! # 接收
132//!
133//! [`Xwmq`] 的接收者 [`XwmqRx`] 具有 [`Send`] 约束,可在线程之间转移所有权,但不能在线程之间共享( [`!Sync`] )。
134//!
135//! 接收者 [`XwmqRx`] 不可被 ”**克隆**“,因为接收者只能有一个。
136//!
137//! 接收消息后,会释放消息槽。若有发送线程正在等待消息槽,将唤醒发送线程。
138//!
139//! ## 首端离队
140//!
141//! 从消息队列的 **首端** 取出消息,称为 **首端离队** 。
142//! 接收成功,消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
143//! 当 [`Box`] 被 [`drop()`] 时,会自动释放heap内存。
144//!
145//! ### 等待离队
146//!
147//! 方法 [`XwmqRx::dq()`] 只可在 **线程** 上下文中使用:
148//!
149//! + 当消息队列中没有消息时,接收线程会阻塞等待。
150//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
151//! + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
152//!
153//! ### 超时等待离队
154//!
155//! 方法 [`XwmqRx::dq_to()`] 只可在 **线程** 上下文中使用:
156//!
157//! + 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
158//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
159//! + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
160//! + 当到达指定的唤醒时间点,线程被唤醒,并通过 [`Err()`] 返回 [`XwmqError::Timedout`] 。
161//!
162//! 方法 [`XwmqRx::dq_unintr()`] 只可在 **线程** 上下文中使用:
163//!
164//! + 当消息队列中没有消息时,接收线程会阻塞等待。
165//! + 接收线程的阻塞等待不可被中断。
166//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
167//!
168//! ### 尝试等待离队
169//!
170//! 方法 [`XwmqRx::trydq()`] 方法可在 **任意** 上下文中使用,不会阻塞,只会检测信号量的值:
171//!
172//! + 当消息队列中没有消息时,立即通过 [`Err()`] 返回 [`XwmqError::NoMsg`] 。
173//! + 当消息队列中有可用的消息时,接收线程会取走一个消息,并释放消息槽。
174//!
175//! ## 尾端离队
176//!
177//! 从消息队列的 **尾端** 取出消息,称为 **尾端离队** 。
178//! 接收成功,消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,
179//! 然后通过 [`Ok()`] 返回。
180//! 当 [`Box`] 被 [`drop()`] 时,会自动释放heap内存。
181//!
182//! ### 等待反向离队
183//!
184//! 方法 [`XwmqRx::rq()`] 只可在 **线程** 上下文中使用:
185//!
186//! + 当消息队列中没有消息时,接收线程会阻塞等待。
187//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
188//! + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
189//!
190//! ### 超时等待反向离队
191//!
192//! 方法 [`XwmqRx::rq_to()`] 只可在 **线程** 上下文中使用:
193//!
194//! + 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
195//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
196//! + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
197//! + 当到达指定的唤醒时间点,线程被唤醒,并通过 [`Err()`] 返回 [`XwmqError::Timedout`] 。
198//!
199//! 方法 [`XwmqRx::rq_unintr()`] 只可在 **线程** 上下文中使用:
200//!
201//! + 当消息队列中没有消息时,接收线程会阻塞等待。
202//! + 接收线程的阻塞等待不可被中断。
203//! + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,并释放消息槽。
204//!
205//! ### 尝试等待反向离队
206//!
207//! 方法 [`XwmqRx::tryrq()`] 方法可在 **任意** 上下文中使用,不会阻塞,只会检测信号量的值:
208//!
209//! + 当消息队列中没有消息时,立即通过 [`Err()`] 返回 [`XwmqError::NoMsg`] 。
210//! + 当消息队列中有可用的消息时,接收线程会取走一个消息,并释放消息槽。
211//!
212//!
213//! # 示例
214//!
215//! [XWOS/xwam/xwrust-example/xwrust_example_xwmq](https://gitee.com/xwos/XWOS/blob/main/xwam/xwrust-example/xwrust_example_xwmq/src/lib.rs)
216//!
217//!
218//! # 对比 [`std::sync::mpsc`]
219//!
220//!
221//! + XWOS RUST:
222//!
223//! ```rust
224//! #![no_std]
225//!
226//! extern crate alloc;
227//!
228//! use xwrust::xwos::thd;
229//! use xwrust::xwmd::xwmq::*;
230//!
231//! static MQ: Xwmq<16, u32> = Xwmq::new();
232//!
233//! pub fn xwrust_example_xwmq() {
234//! println!("XWOS RUST Example: XWMQ");
235//! let (tx, rx) = MQ.init();
236//!
237//! let _ = thd::Builder::new()
238//! .spawn(move |_| { // 子线程闭包
239//! tx.eq(53);
240//! "OK"
241//! });
242//!
243//! let rc = rx.dq();
244//! match rc {
245//! Ok(d) => { // d为接收到的数据,并被放在智能指针Box中
246//! },
247//! Err(e) => {
248//! },
249//! };
250//! }
251//! ```
252//!
253//! + [`std::sync::mpsc`]
254//!
255//! ```rust
256//! use std::thread;
257//! use std::sync::mpsc::sync_channel;
258//!
259//! let (tx, rx) = sync_channel::<i32>(0);
260//! thread::spawn(move|| {
261//! tx.send(53).unwrap();
262//! });
263//! rx.recv().unwrap();
264//! ```
265//!
266//! ### 构建全局变量的方式
267//!
268//! + [`std::sync::mpsc`] 没有编译期构造函数,因此只能借助
269//! 宏 [`lazy_static!`] 创建全局变量;
270//! + [`xwrust::xwmd::xwmq`] 则可以直接在函数外部定义。
271//!
272//!
273//! ### 通道类型
274//!
275//! + [`std::sync::mpsc`] 还有异步的通道 [`std::sync::mpsc::channel()`] ;
276//! + [`xwrust::xwmd::xwmq`] 通过 [`Xwmq::init()`] 返回的是类似于
277//! [`std::sync::mpsc::sync_channel()`] 的通道,
278//! [`xwrust::xwmd::xwmq`] 没有异步的通道 。
279//!
280//! ### 接收消息返回方式不同
281//!
282//! + [`std::sync::mpsc`] 接收到消息后,直接返回类型为 **T** 的消息;
283//! + [`xwrust::xwmd::xwmq`] 则返回 `Box<T>` 。
284//!
285//! [`std::sync::mpsc`]: <https://doc.rust-lang.org/std/sync/mpsc/index.html>
286//! [`std::sync::mpsc::channel()`]: <https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html>
287//! [`std::sync::mpsc::sync_channel()`]: <https://doc.rust-lang.org/std/sync/mpsc/fn.sync_channel.html>
288//! [`static`]: <https://doc.rust-lang.org/std/keyword.static.html>
289//! [`alloc::sync::Arc`]: <https://doc.rust-lang.org/alloc/sync/struct.Arc.html>
290//! [`Send`]: <https://doc.rust-lang.org/core/marker/trait.Send.html>
291//! [`Sync`]: <https://doc.rust-lang.org/core/marker/trait.Sync.html>
292//! [`lazy_static!`]: <https://lib.rs/crates/lazy_static>
293//! [`!Sync`]: <https://doc.rust-lang.org/core/marker/trait.Sync.html>
294//! [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
295//! [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
296//! [`drop()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.drop>
297//! [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
298//! [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
299//! [`xwrust::xwmd::xwmq`]: crate::xwmd::xwmq
300
301extern crate core;
302use core::ffi::*;
303use core::result::Result;
304use core::cell::UnsafeCell;
305use core::ptr;
306use core::marker::PhantomData;
307
308extern crate alloc;
309use alloc::boxed::Box;
310
311use crate::types::*;
312use crate::errno::*;
313
314extern "C" {
315 fn xwmq_init(mq: *mut XwmdXwmq, txq: *mut c_void, num: XwSz) -> XwEr;
316 fn xwmq_fini(mq: *mut XwmdXwmq) -> XwEr;
317 fn xwmq_grab(mq: *mut XwmdXwmq) -> XwEr;
318 fn xwmq_put(mq: *mut XwmdXwmq) -> XwEr;
319 fn xwmq_get_tik(mq: *mut XwmdXwmq) -> XwSq;
320 fn xwrustffi_xwmq_acquire(mq: *mut XwmdXwmq, tik: XwSq) -> XwEr;
321 fn xwrustffi_xwmq_release(mq: *mut XwmdXwmq, tik: XwSq) -> XwEr;
322
323 fn xwmq_eq(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
324 fn xwmq_eq_to(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void, to: XwTm) -> XwEr;
325 fn xwmq_tryeq(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
326 fn xwmq_eq_unintr(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
327 fn xwmq_jq(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
328 fn xwmq_jq_to(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void, to: XwTm) -> XwEr;
329 fn xwmq_jq_unintr(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
330 fn xwmq_tryjq(mq: *mut XwmdXwmq, topic: XwSq, data: *mut c_void) -> XwEr;
331 fn xwmq_dq(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
332 fn xwmq_dq_to(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void, to: XwTm) -> XwEr;
333 fn xwmq_dq_unintr(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
334 fn xwmq_trydq(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
335 fn xwmq_rq(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
336 fn xwmq_rq_to(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void, to: XwTm) -> XwEr;
337 fn xwmq_rq_unintr(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
338 fn xwmq_tryrq(mq: *mut XwmdXwmq, topic: *mut XwSq, data: *mut *mut c_void) -> XwEr;
339}
340
341/// 消息队列的错误码
342#[derive(Debug)]
343pub enum XwmqError {
344 /// 没有错误
345 Ok(XwEr),
346 /// 消息队列没有初始化
347 NotInit(XwEr),
348 /// 等待被中断
349 Interrupt(XwEr),
350 /// 等待超时
351 Timedout(XwEr),
352 /// 不在线程上下文内
353 NotThreadContext(XwEr),
354 /// 抢占被关闭
355 DisPmpt(XwEr),
356 /// 中断底半部被关闭
357 DisBh(XwEr),
358 /// 中断被关闭
359 DisIrq(XwEr),
360 /// 消息队列中没有可用的消息槽
361 NoSlot(XwEr),
362 /// 消息队列中没有消息
363 NoMsg(XwEr),
364 /// 未知错误
365 Unknown(XwEr),
366}
367
368impl XwmqError {
369 /// 消费掉 `XwmqError` 自身,返回内部的错误码。
370 pub fn unwrap(self) -> XwEr {
371 match self {
372 Self::Ok(rc) => rc,
373 Self::NotInit(rc) => rc,
374 Self::Interrupt(rc) => rc,
375 Self::Timedout(rc) => rc,
376 Self::NotThreadContext(rc) => rc,
377 Self::DisPmpt(rc) => rc,
378 Self::DisBh(rc) => rc,
379 Self::DisIrq(rc) => rc,
380 Self::NoSlot(rc) => rc,
381 Self::NoMsg(rc) => rc,
382 Self::Unknown(rc) => rc,
383 }
384 }
385
386 /// 如果信号量的错误码是 [`XwmqError::Ok`] ,返回 `true` 。
387 pub const fn is_ok(&self) -> bool {
388 matches!(*self, Self::Ok(_))
389 }
390
391 /// 如果信号量的错误码不是 [`XwmqError::Ok`] ,返回 `true` 。
392 pub const fn is_err(&self) -> bool {
393 !self.is_ok()
394 }
395}
396
397/// 消息队列对象占用的内存大小
398#[cfg(target_pointer_width = "32")]
399pub const SIZEOF_XWMQ: usize = 200;
400
401/// 消息占用的内存大小
402#[cfg(target_pointer_width = "32")]
403pub const SIZEOF_XWMQ_MSG: usize = 16;
404
405/// 消息队列对象占用的内存大小
406#[cfg(target_pointer_width = "64")]
407pub const SIZEOF_XWMQ: usize = 400;
408
409/// 消息占用的内存大小
410#[cfg(target_pointer_width = "64")]
411pub const SIZEOF_XWMQ_MSG: usize = 32;
412
413/// 用于构建消息队列的内存数组类型
414#[repr(C)]
415#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
416#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
417pub(crate) struct XwmdXwmq {
418 pub(crate) obj: [u8; SIZEOF_XWMQ],
419}
420
421/// 用于构建消息槽的内存数组类型
422#[repr(C)]
423#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
424#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
425pub(crate) struct XwmdXwmqMsg<const N: XwSz>
426where
427 [u8; N * SIZEOF_XWMQ_MSG]: Sized
428{
429 pub(crate) obj: [u8; N * SIZEOF_XWMQ_MSG],
430}
431
432/// 用于构建消息队列的内存数组常量
433///
434/// 此常量的作用是告诉编译器消息队列对象需要多大的内存。
435pub(crate) const XWMQ_INITIALIZER: XwmdXwmq = XwmdXwmq {
436 obj: [0; SIZEOF_XWMQ],
437};
438
439/// 消息队列对象结构体
440pub struct Xwmq<const N: XwSz, T>
441where
442 [u8; N * SIZEOF_XWMQ_MSG]: Sized
443{
444 /// 用于初始化消息队列对象的内存空间
445 pub(crate) mq: UnsafeCell<XwmdXwmq>,
446 /// 用于初始化消息池的内存空间
447 pub(crate) pool: UnsafeCell<XwmdXwmqMsg<N>>,
448 /// 消息队列对象的标签
449 pub(crate) tik: UnsafeCell<XwSq>,
450 phantom: PhantomData<T>,
451}
452
453unsafe impl<const N: XwSz, T> Send for Xwmq<N, T>
454where
455 [u8; N * SIZEOF_XWMQ_MSG]: Sized
456{}
457
458unsafe impl<const N: XwSz, T> Sync for Xwmq<N, T>
459where
460 [u8; N * SIZEOF_XWMQ_MSG]: Sized
461{}
462
463impl<const N: XwSz, T> Xwmq<N, T>
464where
465 [u8; N * SIZEOF_XWMQ_MSG]: Sized
466{
467 /// 新建消息队列对象
468 ///
469 /// 此方法是编译期方法。
470 ///
471 /// # 示例
472 ///
473 /// + 具有 [`static`] 约束的全局变量全局变量:
474 ///
475 /// ```rust
476 /// use xwrust::xwmd::xwmq::*;
477 ///
478 /// static MQ: Xwmq<16, String> = Xwmq::new(); // 16个消息槽,数据类型为String
479 /// ```
480 ///
481 /// + 在heap中创建:
482 ///
483 /// ```rust
484 /// extern crate alloc;
485 /// use alloc::sync::Arc;
486 ///
487 /// use xwrust::xwmd::xwmq::*;
488 ///
489 /// pub fn xwrust_example_xwmq() {
490 /// let mq: Arc<Xwmq<16, String>> = Arc::new(Xwmq::new()); // 16个消息槽,数据类型为String
491 /// }
492 /// ```
493 ///
494 /// [`static`]: https://doc.rust-lang.org/std/keyword.static.html
495 pub const fn new() -> Self {
496 Self {
497 mq: UnsafeCell::new(XWMQ_INITIALIZER),
498 pool: UnsafeCell::new(XwmdXwmqMsg { obj: [0; N * SIZEOF_XWMQ_MSG] }),
499 tik: UnsafeCell::new(0),
500 phantom: PhantomData,
501 }
502 }
503
504 /// 初始化消息队列对象
505 ///
506 /// 消息队列对象必须调用此方法一次,方可正常使用。
507 /// 初始化后会返回消息队列的发送者 [`XwmqTx`] 以及接收者 [`XwmqRx`] 。
508 ///
509 /// # 示例
510 ///
511 /// ```rust
512 /// use xwrust::xwmd::xwmq::*;
513 ///
514 /// static MQ: Xwmq<16, String> = Xwmq::new();
515 ///
516 /// pub fn xwrust_example_xwmq() {
517 /// let (tx, rx) = MQ.init();
518 /// }
519 /// ```
520 pub fn init<'a>(&'a self) -> (XwmqTx<'a, N, T>, XwmqRx<'a, N, T>) {
521 unsafe {
522 xwmq_init(self.mq.get(), self.pool.get() as _, N);
523 *self.tik.get() = xwmq_get_tik(self.mq.get());
524 }
525 (XwmqTx {xwmq: &self}, XwmqRx {xwmq: &self})
526 }
527}
528
529#[derive(Clone)]
530pub struct XwmqTx<'a, const N: XwSz, T>
531where
532 [u8; N * SIZEOF_XWMQ_MSG]: Sized
533{
534 xwmq: &'a Xwmq<N, T>,
535}
536
537pub struct XwmqRx<'a, const N: XwSz, T>
538where
539 [u8; N * SIZEOF_XWMQ_MSG]: Sized
540{
541 xwmq: &'a Xwmq<N, T>,
542}
543
544unsafe impl<'a, const N: XwSz, T> Send for XwmqTx<'a, N, T>
545where
546 [u8; N * SIZEOF_XWMQ_MSG]: Sized
547{}
548
549impl<'a, const N: XwSz, T> !Sync for XwmqTx<'a, N, T>
550where
551 [u8; N * SIZEOF_XWMQ_MSG]: Sized
552{}
553
554unsafe impl<'a, const N: XwSz, T> Send for XwmqRx<'a, N, T>
555where
556 [u8; N * SIZEOF_XWMQ_MSG]: Sized
557{}
558
559impl<'a, const N: XwSz, T> !Sync for XwmqRx<'a, N, T>
560where
561 [u8; N * SIZEOF_XWMQ_MSG]: Sized
562{}
563
564impl<'a, const N: XwSz, T> XwmqTx<'a, N, T>
565where
566 [u8; N * SIZEOF_XWMQ_MSG]: Sized
567{
568 /// 等待消息槽,成功后将消息发送到消息队列的 **尾端** (入队)
569 ///
570 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
571 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
572 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
573 /// + 当发送线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
574 ///
575 /// # 参数说明
576 ///
577 /// + data: 类型为 `T` 的数据
578 ///
579 /// # 上下文
580 ///
581 /// + 线程
582 ///
583 /// # 错误码
584 ///
585 /// + [`XwmqError::Ok`] 没有错误
586 /// + [`XwmqError::NotInit`] 消息队列没有初始化
587 /// + [`XwmqError::Interrupt`] 等待被中断
588 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
589 /// + [`XwmqError::DisPmpt`] 抢占被关闭
590 /// + [`XwmqError::DisBh`] 中断底半部被关闭
591 /// + [`XwmqError::DisIrq`] 中断被关闭
592 ///
593 /// # 示例
594 ///
595 /// ```rust
596 /// extern crate alloc;
597 /// use alloc::string::String;
598 /// use alloc::string::ToString;
599 ///
600 /// use xwrust::xwmd::xwmq::*;
601 ///
602 /// static MQ: Xwmq<16, String> = Xwmq::new();
603 ///
604 /// pub fn xwrust_example_xwmq() {
605 /// let (tx, rx) = MQ.init();
606 /// // ...省略...
607 /// tx.eq("message".to_string());
608 /// // ...省略...
609 /// }
610 /// ```
611 ///
612 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
613 pub fn eq(&self, data: T) -> XwmqError {
614 let boxdata = Box::new(data);
615 let raw = Box::into_raw(boxdata);
616 unsafe {
617 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
618 if rc == 0 {
619 rc = xwmq_eq(self.xwmq.mq.get(), 0, raw as *mut c_void);
620 xwmq_put(self.xwmq.mq.get());
621 if XWOK == rc {
622 XwmqError::Ok(rc)
623 } else if -EINTR == rc {
624 XwmqError::Interrupt(rc)
625 } else if -ENOTTHDCTX == rc {
626 XwmqError::NotThreadContext(rc)
627 } else if -EDISPMPT == rc {
628 XwmqError::DisPmpt(rc)
629 } else if -EDISBH == rc {
630 XwmqError::DisBh(rc)
631 } else if -EDISIRQ == rc {
632 XwmqError::DisIrq(rc)
633 } else {
634 XwmqError::Unknown(rc)
635 }
636 } else {
637 XwmqError::NotInit(rc)
638 }
639 }
640 }
641
642 /// 限时等待消息槽,成功后将消息发送到消息队列的 **尾端** (入队)
643 ///
644 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
645 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
646 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
647 /// + 当发送线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
648 /// + 当到达指定的唤醒时间点,线程被唤醒,并返回 [`XwmqError::Timedout`] 。
649 ///
650 /// # 参数说明
651 ///
652 /// + data: 类型为 `T` 的数据
653 /// + to: 期望唤醒的时间点
654 ///
655 /// # 上下文
656 ///
657 /// + 线程
658 ///
659 /// # 错误码
660 ///
661 /// + [`XwmqError::Ok`] 没有错误
662 /// + [`XwmqError::NotInit`] 消息队列没有初始化
663 /// + [`XwmqError::Interrupt`] 等待被中断
664 /// + [`XwmqError::Timedout`] 等待超时
665 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
666 /// + [`XwmqError::DisPmpt`] 抢占被关闭
667 /// + [`XwmqError::DisBh`] 中断底半部被关闭
668 /// + [`XwmqError::DisIrq`] 中断被关闭
669 ///
670 /// # 示例
671 ///
672 /// ```rust
673 /// extern crate alloc;
674 /// use alloc::string::String;
675 /// use alloc::string::ToString;
676 ///
677 /// use xwrust::xwtm;
678 /// use xwrust::xwmd::xwmq::*;
679 ///
680 /// static MQ: Xwmq<16, String> = Xwmq::new();
681 ///
682 /// pub fn xwrust_example_xwmq() {
683 /// let (tx, rx) = MQ.init();
684 /// // ...省略...
685 /// tx.eq_to("message".to_string(), xwtm::ft(xwtm::s(1)));
686 /// // ...省略...
687 /// }
688 /// ```
689 ///
690 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
691 pub fn eq_to(&self, data: T, to: XwTm) -> XwmqError {
692 let boxdata = Box::new(data);
693 let raw = Box::into_raw(boxdata);
694 unsafe {
695 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
696 if rc == 0 {
697 rc = xwmq_eq_to(self.xwmq.mq.get(), 0, raw as *mut c_void, to);
698 xwmq_put(self.xwmq.mq.get());
699 if XWOK == rc {
700 XwmqError::Ok(rc)
701 } else if -EINTR == rc {
702 XwmqError::Interrupt(rc)
703 } else if -ETIMEDOUT == rc {
704 XwmqError::Timedout(rc)
705 } else if -ENOTTHDCTX == rc {
706 XwmqError::NotThreadContext(rc)
707 } else if -EDISPMPT == rc {
708 XwmqError::DisPmpt(rc)
709 } else if -EDISBH == rc {
710 XwmqError::DisBh(rc)
711 } else if -EDISIRQ == rc {
712 XwmqError::DisIrq(rc)
713 } else {
714 XwmqError::Unknown(rc)
715 }
716 } else {
717 XwmqError::NotInit(rc)
718 }
719 }
720 }
721
722 /// 等待消息槽,且等待不可被中断,成功后将消息发送到消息队列的 **尾端** (入队)
723 ///
724 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
725 /// + 发送线程的阻塞等待不可被中断。
726 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
727 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
728 ///
729 /// # 参数说明
730 ///
731 /// + data: 类型为 `T` 的数据
732 ///
733 /// # 上下文
734 ///
735 /// + 线程
736 ///
737 /// # 错误码
738 ///
739 /// + [`XwmqError::Ok`] 没有错误
740 /// + [`XwmqError::NotInit`] 消息队列没有初始化
741 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
742 /// + [`XwmqError::DisPmpt`] 抢占被关闭
743 /// + [`XwmqError::DisBh`] 中断底半部被关闭
744 /// + [`XwmqError::DisIrq`] 中断被关闭
745 ///
746 /// # 示例
747 ///
748 /// ```rust
749 /// extern crate alloc;
750 /// use alloc::string::String;
751 /// use alloc::string::ToString;
752 ///
753 /// use xwrust::xwmd::xwmq::*;
754 ///
755 /// static MQ: Xwmq<16, String> = Xwmq::new();
756 ///
757 /// pub fn xwrust_example_xwmq() {
758 /// let (tx, rx) = MQ.init();
759 /// // ...省略...
760 /// tx.eq_unintr("message".to_string());
761 /// // ...省略...
762 /// }
763 /// ```
764 ///
765 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
766 pub fn eq_unintr(&self, data: T) -> XwmqError {
767 let boxdata = Box::new(data);
768 let raw = Box::into_raw(boxdata);
769 unsafe {
770 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
771 if rc == 0 {
772 rc = xwmq_eq_unintr(self.xwmq.mq.get(), 0, raw as *mut c_void);
773 xwmq_put(self.xwmq.mq.get());
774 if XWOK == rc {
775 XwmqError::Ok(rc)
776 } else if -ENOTTHDCTX == rc {
777 XwmqError::NotThreadContext(rc)
778 } else if -EDISPMPT == rc {
779 XwmqError::DisPmpt(rc)
780 } else if -EDISBH == rc {
781 XwmqError::DisBh(rc)
782 } else if -EDISIRQ == rc {
783 XwmqError::DisIrq(rc)
784 } else {
785 XwmqError::Unknown(rc)
786 }
787 } else {
788 XwmqError::NotInit(rc)
789 }
790 }
791 }
792
793 /// 尝试获取消息槽,成功后将消息发送到消息队列的 **尾端** (入队)
794 ///
795 /// + 当消息队列中没有可用的消息槽可用时,立即返回 [`XwmqError::NoSlot`] 。
796 /// + 当消息队列中有可用的消息槽时,取走一个消息槽,用于发送数据。
797 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
798 ///
799 /// # 参数说明
800 ///
801 /// + data: 类型为 `T` 的数据
802 ///
803 /// # 上下文
804 ///
805 /// + 任意
806 ///
807 /// # 错误码
808 ///
809 /// + [`XwmqError::Ok`] 没有错误
810 /// + [`XwmqError::NotInit`] 消息队列没有初始化
811 /// + [`XwmqError::NoSlot`] 消息队列中没有可用的消息槽
812 ///
813 /// # 示例
814 ///
815 /// ```rust
816 /// extern crate alloc;
817 /// use alloc::string::String;
818 /// use alloc::string::ToString;
819 ///
820 /// use xwrust::xwmd::xwmq::*;
821 ///
822 /// static MQ: Xwmq<16, String> = Xwmq::new();
823 ///
824 /// pub fn xwrust_example_xwmq() {
825 /// let (tx, rx) = MQ.init();
826 /// // ...省略...
827 /// tx.tryeq("message".to_string());
828 /// // ...省略...
829 /// }
830 /// ```
831 ///
832 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
833 pub fn tryeq(&self, data: T) -> XwmqError {
834 let boxdata = Box::new(data);
835 let raw = Box::into_raw(boxdata);
836 unsafe {
837 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
838 if rc == 0 {
839 rc = xwmq_tryeq(self.xwmq.mq.get(), 0, raw as *mut c_void);
840 xwmq_put(self.xwmq.mq.get());
841 if XWOK == rc {
842 XwmqError::Ok(rc)
843 } else if -ENODATA == rc {
844 XwmqError::NoSlot(rc)
845 } else {
846 XwmqError::Unknown(rc)
847 }
848 } else {
849 XwmqError::NotInit(rc)
850 }
851 }
852 }
853
854 /// 等待消息槽,成功后将消息发送到消息队列的 **首端** (插队)
855 ///
856 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
857 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
858 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
859 /// + 当发送线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
860 ///
861 /// # 参数说明
862 ///
863 /// + data: 类型为 `T` 的数据
864 ///
865 /// # 上下文
866 ///
867 /// + 线程
868 ///
869 /// # 错误码
870 ///
871 /// + [`XwmqError::Ok`] 没有错误
872 /// + [`XwmqError::NotInit`] 消息队列没有初始化
873 /// + [`XwmqError::Interrupt`] 等待被中断
874 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
875 /// + [`XwmqError::DisPmpt`] 抢占被关闭
876 /// + [`XwmqError::DisBh`] 中断底半部被关闭
877 /// + [`XwmqError::DisIrq`] 中断被关闭
878 ///
879 /// # 示例
880 ///
881 /// ```rust
882 /// extern crate alloc;
883 /// use alloc::string::String;
884 /// use alloc::string::ToString;
885 ///
886 /// use xwrust::xwmd::xwmq::*;
887 ///
888 /// static MQ: Xwmq<16, String> = Xwmq::new();
889 ///
890 /// pub fn xwrust_example_xwmq() {
891 /// let (tx, rx) = MQ.init();
892 /// // ...省略...
893 /// tx.jq("message".to_string());
894 /// // ...省略...
895 /// }
896 /// ```
897 ///
898 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
899 pub fn jq(&self, data: T) -> XwmqError {
900 let boxdata = Box::new(data);
901 let raw = Box::into_raw(boxdata);
902 unsafe {
903 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
904 if rc == 0 {
905 rc = xwmq_jq(self.xwmq.mq.get(), 0, raw as *mut c_void);
906 xwmq_put(self.xwmq.mq.get());
907 if XWOK == rc {
908 XwmqError::Ok(rc)
909 } else if -EINTR == rc {
910 XwmqError::Interrupt(rc)
911 } else if -ENOTTHDCTX == rc {
912 XwmqError::NotThreadContext(rc)
913 } else if -EDISPMPT == rc {
914 XwmqError::DisPmpt(rc)
915 } else if -EDISBH == rc {
916 XwmqError::DisBh(rc)
917 } else if -EDISIRQ == rc {
918 XwmqError::DisIrq(rc)
919 } else {
920 XwmqError::Unknown(rc)
921 }
922 } else {
923 XwmqError::NotInit(rc)
924 }
925 }
926 }
927
928 /// 限时等待消息槽,成功后将消息发送到消息队列的 **首端** (插队)
929 ///
930 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待,等待时会指定一个唤醒时间点。
931 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
932 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
933 /// + 当发送线程阻塞等待被中断时,返回 [`XwmqError::Interrupt`] 。
934 /// + 当到达指定的唤醒时间点,线程被唤醒,并返回 [`XwmqError::Timedout`] 。
935 ///
936 /// # 参数说明
937 ///
938 /// + data: 类型为 `T` 的数据
939 /// + to: 期望唤醒的时间点
940 ///
941 /// # 上下文
942 ///
943 /// + 线程
944 ///
945 /// # 错误码
946 ///
947 /// + [`XwmqError::Ok`] 没有错误
948 /// + [`XwmqError::NotInit`] 消息队列没有初始化
949 /// + [`XwmqError::Interrupt`] 等待被中断
950 /// + [`XwmqError::Timedout`] 等待超时
951 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
952 /// + [`XwmqError::DisPmpt`] 抢占被关闭
953 /// + [`XwmqError::DisBh`] 中断底半部被关闭
954 /// + [`XwmqError::DisIrq`] 中断被关闭
955 ///
956 /// # 示例
957 ///
958 /// ```rust
959 /// extern crate alloc;
960 /// use alloc::string::String;
961 /// use alloc::string::ToString;
962 ///
963 /// use xwrust::xwtm;
964 /// use xwrust::xwmd::xwmq::*;
965 ///
966 /// static MQ: Xwmq<16, String> = Xwmq::new();
967 ///
968 /// pub fn xwrust_example_xwmq() {
969 /// let (tx, rx) = MQ.init();
970 /// // ...省略...
971 /// tx.jq_to("message".to_string(), xwtm::ft(xwtm::s(1)));
972 /// // ...省略...
973 /// }
974 /// ```
975 ///
976 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
977 pub fn jq_to(&self, data: T, to: XwTm) -> XwmqError {
978 let boxdata = Box::new(data);
979 let raw = Box::into_raw(boxdata);
980 unsafe {
981 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
982 if rc == 0 {
983 rc = xwmq_jq_to(self.xwmq.mq.get(), 0, raw as *mut c_void, to);
984 xwmq_put(self.xwmq.mq.get());
985 if XWOK == rc {
986 XwmqError::Ok(rc)
987 } else if -EINTR == rc {
988 XwmqError::Interrupt(rc)
989 } else if -ETIMEDOUT == rc {
990 XwmqError::Timedout(rc)
991 } else if -ENOTTHDCTX == rc {
992 XwmqError::NotThreadContext(rc)
993 } else if -EDISPMPT == rc {
994 XwmqError::DisPmpt(rc)
995 } else if -EDISBH == rc {
996 XwmqError::DisBh(rc)
997 } else if -EDISIRQ == rc {
998 XwmqError::DisIrq(rc)
999 } else {
1000 XwmqError::Unknown(rc)
1001 }
1002 } else {
1003 XwmqError::NotInit(rc)
1004 }
1005 }
1006 }
1007
1008 /// 等待消息槽,且等待不可被中断,成功后将消息发送到消息队列的 **首端** (插队)
1009 ///
1010 /// + 当消息队列中没有可用的消息槽可用时,发送线程会阻塞等待。
1011 /// + 发送线程的阻塞等待不可被中断。
1012 /// + 当消息队列中有可用的消息槽时,发送线程被唤醒,并取走一个消息槽,用于发送数据。
1013 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
1014 ///
1015 /// # 参数说明
1016 ///
1017 /// + data: 类型为 `T` 的数据
1018 ///
1019 /// # 上下文
1020 ///
1021 /// + 线程
1022 ///
1023 /// # 错误码
1024 ///
1025 /// + [`XwmqError::Ok`] 没有错误
1026 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1027 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1028 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1029 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1030 /// + [`XwmqError::DisIrq`] 中断被关闭
1031 ///
1032 /// # 示例
1033 ///
1034 /// ```rust
1035 /// extern crate alloc;
1036 /// use alloc::string::String;
1037 /// use alloc::string::ToString;
1038 ///
1039 /// use xwrust::xwmd::xwmq::*;
1040 ///
1041 /// static MQ: Xwmq<16, String> = Xwmq::new();
1042 ///
1043 /// pub fn xwrust_example_xwmq() {
1044 /// let (tx, rx) = MQ.init();
1045 /// // ...省略...
1046 /// tx.jq_unintr("message".to_string());
1047 /// // ...省略...
1048 /// }
1049 /// ```
1050 ///
1051 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1052 pub fn jq_unintr(&self, data: T) -> XwmqError {
1053 let boxdata = Box::new(data);
1054 let raw = Box::into_raw(boxdata);
1055 unsafe {
1056 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1057 if rc == 0 {
1058 rc = xwmq_jq_unintr(self.xwmq.mq.get(), 0, raw as *mut c_void);
1059 xwmq_put(self.xwmq.mq.get());
1060 if XWOK == rc {
1061 XwmqError::Ok(rc)
1062 } else if -ENOTTHDCTX == rc {
1063 XwmqError::NotThreadContext(rc)
1064 } else if -EDISPMPT == rc {
1065 XwmqError::DisPmpt(rc)
1066 } else if -EDISBH == rc {
1067 XwmqError::DisBh(rc)
1068 } else if -EDISIRQ == rc {
1069 XwmqError::DisIrq(rc)
1070 } else {
1071 XwmqError::Unknown(rc)
1072 }
1073 } else {
1074 XwmqError::NotInit(rc)
1075 }
1076 }
1077 }
1078
1079 /// 尝试获取消息槽,成功后将消息发送到消息队列的 **首端** (插队)
1080 ///
1081 /// + 当消息队列中没有可用的消息槽可用时,立即返回 [`XwmqError::NoSlot`] 。
1082 /// + 当消息队列中有可用的消息槽时,取走一个消息槽,用于发送数据。
1083 /// + 消息 **入队** 时,会通过 [`Box`] 将数据放入heap中,然后进行发送。
1084 ///
1085 /// # 参数说明
1086 ///
1087 /// + data: 类型为 `T` 的数据
1088 ///
1089 /// # 上下文
1090 ///
1091 /// + 任意
1092 ///
1093 /// # 错误码
1094 ///
1095 /// + [`XwmqError::Ok`] 没有错误
1096 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1097 /// + [`XwmqError::NoSlot`] 消息队列中没有可用的消息槽
1098 ///
1099 /// # 示例
1100 ///
1101 /// ```rust
1102 /// extern crate alloc;
1103 /// use alloc::string::String;
1104 /// use alloc::string::ToString;
1105 ///
1106 /// use xwrust::xwmd::xwmq::*;
1107 ///
1108 /// static MQ: Xwmq<16, String> = Xwmq::new();
1109 ///
1110 /// pub fn xwrust_example_xwmq() {
1111 /// let (tx, rx) = MQ.init();
1112 /// // ...省略...
1113 /// tx.tryjq("message".to_string());
1114 /// // ...省略...
1115 /// }
1116 /// ```
1117 ///
1118 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1119 pub fn tryjq(&self, data: T) -> XwmqError {
1120 let boxdata = Box::new(data);
1121 let raw = Box::into_raw(boxdata);
1122 unsafe {
1123 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1124 if rc == 0 {
1125 rc = xwmq_tryjq(self.xwmq.mq.get(), 0, raw as *mut c_void);
1126 xwmq_put(self.xwmq.mq.get());
1127 if XWOK == rc {
1128 XwmqError::Ok(rc)
1129 } else if -ENODATA == rc {
1130 XwmqError::NoSlot(rc)
1131 } else {
1132 XwmqError::Unknown(rc)
1133 }
1134 } else {
1135 XwmqError::NotInit(rc)
1136 }
1137 }
1138 }
1139}
1140
1141impl<'a, const N: XwSz, T> XwmqRx<'a, N, T>
1142where
1143 [u8; N * SIZEOF_XWMQ_MSG]: Sized
1144{
1145 /// 等待从消息队列 **首端** 接收一条消息
1146 ///
1147 /// + 从消息队列的 **首端** 取出消息,称为 **离队** 。
1148 /// + 当消息队列中没有消息时,接收线程会阻塞等待。
1149 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1150 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1151 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1152 /// + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
1153 ///
1154 /// # 上下文
1155 ///
1156 /// + 线程
1157 ///
1158 /// # 错误码
1159 ///
1160 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1161 /// + [`XwmqError::Interrupt`] 等待被中断
1162 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1163 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1164 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1165 /// + [`XwmqError::DisIrq`] 中断被关闭
1166 ///
1167 /// # 示例
1168 ///
1169 /// ```rust
1170 /// extern crate alloc;
1171 /// use alloc::string::String;
1172 /// use alloc::string::ToString;
1173 ///
1174 /// use xwrust::xwmd::xwmq::*;
1175 ///
1176 /// static MQ: Xwmq<16, String> = Xwmq::new();
1177 ///
1178 /// pub fn xwrust_example_xwmq() {
1179 /// let (tx, rx) = MQ.init();
1180 /// // ...省略...
1181 /// let rc = rx.dq();
1182 /// match rc {
1183 /// Ok(d) => { // d是Box<String>
1184 /// },
1185 /// Err(e) => { // e是错误码
1186 /// },
1187 /// };
1188 /// // ...省略...
1189 /// }
1190 /// ```
1191 ///
1192 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1193 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1194 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1195 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1196 pub fn dq(&self) -> Result<Box<T>, XwmqError> {
1197 unsafe {
1198 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1199 if rc == 0 {
1200 let mut topic = 0;
1201 let mut raw: *mut c_void = ptr::null_mut();
1202 rc = xwmq_dq(self.xwmq.mq.get(), &mut topic, &mut raw);
1203 xwmq_put(self.xwmq.mq.get());
1204 if XWOK == rc {
1205 let boxdata = Box::from_raw(raw as *mut T);
1206 Ok(boxdata)
1207 } else if -EINTR == rc {
1208 Err(XwmqError::Interrupt(rc))
1209 } else if -ENOTTHDCTX == rc {
1210 Err(XwmqError::NotThreadContext(rc))
1211 } else if -EDISPMPT == rc {
1212 Err(XwmqError::DisPmpt(rc))
1213 } else if -EDISBH == rc {
1214 Err(XwmqError::DisBh(rc))
1215 } else if -EDISIRQ == rc {
1216 Err(XwmqError::DisIrq(rc))
1217 } else {
1218 Err(XwmqError::Unknown(rc))
1219 }
1220 } else {
1221 Err(XwmqError::NotInit(rc))
1222 }
1223 }
1224 }
1225
1226 /// 限时等待从消息队列 **首端** 接收一条消息
1227 ///
1228 /// + 从消息队列的 **首端** 取出消息,称为 **离队** 。
1229 /// + 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
1230 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1231 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1232 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1233 /// + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
1234 /// + 当到达指定的唤醒时间点,线程被唤醒,并通过 [`Err()`] 返回 [`XwmqError::Timedout`] 。
1235 ///
1236 /// # 参数说明
1237 ///
1238 /// + to: 期望唤醒的时间点
1239 ///
1240 /// # 上下文
1241 ///
1242 /// + 线程
1243 ///
1244 /// # 错误码
1245 ///
1246 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1247 /// + [`XwmqError::Interrupt`] 等待被中断
1248 /// + [`XwmqError::Timedout`] 等待超时
1249 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1250 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1251 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1252 /// + [`XwmqError::DisIrq`] 中断被关闭
1253 ///
1254 /// # 示例
1255 ///
1256 /// ```rust
1257 /// extern crate alloc;
1258 /// use alloc::string::String;
1259 /// use alloc::string::ToString;
1260 ///
1261 /// use xwrust::xwtm;
1262 /// use xwrust::xwmd::xwmq::*;
1263 ///
1264 /// static MQ: Xwmq<16, String> = Xwmq::new();
1265 ///
1266 /// pub fn xwrust_example_xwmq() {
1267 /// let (tx, rx) = MQ.init();
1268 /// // ...省略...
1269 /// let rc = rx.dq_to(xwtm::ft(xwtm::s(1)));
1270 /// match rc {
1271 /// Ok(d) => { // d是Box<String>
1272 /// },
1273 /// Err(e) => { // e是错误码
1274 /// },
1275 /// };
1276 /// // ...省略...
1277 /// }
1278 /// ```
1279 ///
1280 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1281 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1282 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1283 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1284 pub fn dq_to(&self, to: XwTm) -> Result<Box<T>, XwmqError> {
1285 unsafe {
1286 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1287 if rc == 0 {
1288 let mut topic = 0;
1289 let mut raw: *mut c_void = ptr::null_mut();
1290 rc = xwmq_dq_to(self.xwmq.mq.get(), &mut topic, &mut raw, to);
1291 xwmq_put(self.xwmq.mq.get());
1292 if XWOK == rc {
1293 let boxdata = Box::from_raw(raw as *mut T);
1294 Ok(boxdata)
1295 } else if -EINTR == rc {
1296 Err(XwmqError::Interrupt(rc))
1297 } else if -ETIMEDOUT == rc {
1298 Err(XwmqError::Timedout(rc))
1299 } else if -ENOTTHDCTX == rc {
1300 Err(XwmqError::NotThreadContext(rc))
1301 } else if -EDISPMPT == rc {
1302 Err(XwmqError::DisPmpt(rc))
1303 } else if -EDISBH == rc {
1304 Err(XwmqError::DisBh(rc))
1305 } else if -EDISIRQ == rc {
1306 Err(XwmqError::DisIrq(rc))
1307 } else {
1308 Err(XwmqError::Unknown(rc))
1309 }
1310 } else {
1311 Err(XwmqError::NotInit(rc))
1312 }
1313 }
1314 }
1315
1316 /// 等待从消息队列 **首端** 接收一条消息,且等待不可被中断
1317 ///
1318 /// + 从消息队列的 **首端** 取出消息,称为 **离队** 。
1319 /// + 当消息队列中没有消息时,接收线程会阻塞等待。
1320 /// + 接收线程的阻塞等待不可被中断。
1321 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1322 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1323 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1324 ///
1325 /// # 上下文
1326 ///
1327 /// + 线程
1328 ///
1329 /// # 错误码
1330 ///
1331 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1332 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1333 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1334 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1335 /// + [`XwmqError::DisIrq`] 中断被关闭
1336 ///
1337 /// # 示例
1338 ///
1339 /// ```rust
1340 /// extern crate alloc;
1341 /// use alloc::string::String;
1342 /// use alloc::string::ToString;
1343 ///
1344 /// use xwrust::xwmd::xwmq::*;
1345 ///
1346 /// static MQ: Xwmq<16, String> = Xwmq::new();
1347 ///
1348 /// pub fn xwrust_example_xwmq() {
1349 /// let (tx, rx) = MQ.init();
1350 /// // ...省略...
1351 /// let rc = rx.dq();
1352 /// match rc {
1353 /// Ok(d) => { // d是Box<String>
1354 /// },
1355 /// Err(e) => { // e是错误码
1356 /// },
1357 /// };
1358 /// // ...省略...
1359 /// }
1360 /// ```
1361 ///
1362 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1363 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1364 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1365 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1366 pub fn dq_unintr(&self) -> Result<Box<T>, XwmqError> {
1367 unsafe {
1368 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1369 if rc == 0 {
1370 let mut topic = 0;
1371 let mut raw: *mut c_void = ptr::null_mut();
1372 rc = xwmq_dq_unintr(self.xwmq.mq.get(), &mut topic, &mut raw);
1373 xwmq_put(self.xwmq.mq.get());
1374 if XWOK == rc {
1375 let boxdata = Box::from_raw(raw as *mut T);
1376 Ok(boxdata)
1377 } else if -ENOTTHDCTX == rc {
1378 Err(XwmqError::NotThreadContext(rc))
1379 } else if -EDISPMPT == rc {
1380 Err(XwmqError::DisPmpt(rc))
1381 } else if -EDISBH == rc {
1382 Err(XwmqError::DisBh(rc))
1383 } else if -EDISIRQ == rc {
1384 Err(XwmqError::DisIrq(rc))
1385 } else {
1386 Err(XwmqError::Unknown(rc))
1387 }
1388 } else {
1389 Err(XwmqError::NotInit(rc))
1390 }
1391 }
1392 }
1393
1394 /// 尝试从消息队列 **首端** 接收一条消息
1395 ///
1396 /// + 从消息队列的 **首端** 取出消息,称为 **离队** 。
1397 /// + 当消息队列中没有消息时,立即通过 [`Err()`] 返回 [`XwmqError::NoMsg`] 。
1398 /// + 当消息队列中有可用的消息时,会取走一个消息,并释放消息槽。
1399 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1400 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1401 ///
1402 /// # 上下文
1403 ///
1404 /// + 任意
1405 ///
1406 /// # 错误码
1407 ///
1408 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1409 /// + [`XwmqError::NoMsg`] 消息队列中没有消息
1410 ///
1411 /// # 示例
1412 ///
1413 /// ```rust
1414 /// extern crate alloc;
1415 /// use alloc::string::String;
1416 /// use alloc::string::ToString;
1417 ///
1418 /// use xwrust::xwmd::xwmq::*;
1419 ///
1420 /// static MQ: Xwmq<16, String> = Xwmq::new();
1421 ///
1422 /// pub fn xwrust_example_xwmq() {
1423 /// let (tx, rx) = MQ.init();
1424 /// // ...省略...
1425 /// let rc = rx.trydq();
1426 /// match rc {
1427 /// Ok(d) => { // d是Box<String>
1428 /// },
1429 /// Err(e) => { // e是错误码
1430 /// },
1431 /// };
1432 /// // ...省略...
1433 /// }
1434 /// ```
1435 ///
1436 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1437 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1438 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1439 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1440 pub fn trydq(&self) -> Result<Box<T>, XwmqError> {
1441 unsafe {
1442 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1443 if rc == 0 {
1444 let mut topic = 0;
1445 let mut raw: *mut c_void = ptr::null_mut();
1446 rc = xwmq_trydq(self.xwmq.mq.get(), &mut topic, &mut raw);
1447 xwmq_put(self.xwmq.mq.get());
1448 if XWOK == rc {
1449 let boxdata = Box::from_raw(raw as *mut T);
1450 Ok(boxdata)
1451 } else if -ENODATA == rc {
1452 Err(XwmqError::NoMsg(rc))
1453 } else {
1454 Err(XwmqError::Unknown(rc))
1455 }
1456 } else {
1457 Err(XwmqError::NotInit(rc))
1458 }
1459 }
1460 }
1461
1462 /// 等待从消息队列 **尾端** 接收一条消息
1463 ///
1464 /// + 从消息队列的 **尾端** 取出消息,称为 **反向离队** 。
1465 /// + 当消息队列中没有消息时,接收线程会阻塞等待。
1466 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1467 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1468 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1469 /// + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
1470 ///
1471 /// # 上下文
1472 ///
1473 /// + 线程
1474 ///
1475 /// # 错误码
1476 ///
1477 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1478 /// + [`XwmqError::Interrupt`] 等待被中断
1479 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1480 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1481 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1482 /// + [`XwmqError::DisIrq`] 中断被关闭
1483 ///
1484 /// # 示例
1485 ///
1486 /// ```rust
1487 /// extern crate alloc;
1488 /// use alloc::string::String;
1489 /// use alloc::string::ToString;
1490 ///
1491 /// use xwrust::xwmd::xwmq::*;
1492 ///
1493 /// static MQ: Xwmq<16, String> = Xwmq::new();
1494 ///
1495 /// pub fn xwrust_example_xwmq() {
1496 /// let (tx, rx) = MQ.init();
1497 /// // ...省略...
1498 /// let rc = rx.rq();
1499 /// match rc {
1500 /// Ok(d) => { // d是Box<String>
1501 /// },
1502 /// Err(e) => { // e是错误码
1503 /// },
1504 /// };
1505 /// // ...省略...
1506 /// }
1507 /// ```
1508 ///
1509 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1510 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1511 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1512 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1513 pub fn rq(&self) -> Result<Box<T>, XwmqError> {
1514 unsafe {
1515 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1516 if rc == 0 {
1517 let mut topic = 0;
1518 let mut raw: *mut c_void = ptr::null_mut();
1519 rc = xwmq_rq(self.xwmq.mq.get(), &mut topic, &mut raw);
1520 xwmq_put(self.xwmq.mq.get());
1521 if XWOK == rc {
1522 let boxdata = Box::from_raw(raw as *mut T);
1523 Ok(boxdata)
1524 } else if -EINTR == rc {
1525 Err(XwmqError::Interrupt(rc))
1526 } else if -ENOTTHDCTX == rc {
1527 Err(XwmqError::NotThreadContext(rc))
1528 } else if -EDISPMPT == rc {
1529 Err(XwmqError::DisPmpt(rc))
1530 } else if -EDISBH == rc {
1531 Err(XwmqError::DisBh(rc))
1532 } else if -EDISIRQ == rc {
1533 Err(XwmqError::DisIrq(rc))
1534 } else {
1535 Err(XwmqError::Unknown(rc))
1536 }
1537 } else {
1538 Err(XwmqError::NotInit(rc))
1539 }
1540 }
1541 }
1542
1543 /// 限时等待从消息队列 **尾端** 接收一条消息
1544 ///
1545 /// + 从消息队列的 **尾端** 取出消息,称为 **反向离队** 。
1546 /// + 当消息队列中没有消息时,接收线程会阻塞等待,等待时会指定一个唤醒时间点。
1547 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1548 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1549 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1550 /// + 当线程阻塞等待被中断时,通过 [`Err()`] 返回 [`XwmqError::Interrupt`] 。
1551 /// + 当到达指定的唤醒时间点,线程被唤醒,并通过 [`Err()`] 返回 [`XwmqError::Timedout`] 。
1552 ///
1553 /// # 参数说明
1554 ///
1555 /// + to: 期望唤醒的时间点
1556 ///
1557 /// # 上下文
1558 ///
1559 /// + 线程
1560 ///
1561 /// # 错误码
1562 ///
1563 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1564 /// + [`XwmqError::Interrupt`] 等待被中断
1565 /// + [`XwmqError::Timedout`] 等待超时
1566 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1567 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1568 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1569 /// + [`XwmqError::DisIrq`] 中断被关闭
1570 ///
1571 /// # 示例
1572 ///
1573 /// ```rust
1574 /// extern crate alloc;
1575 /// use alloc::string::String;
1576 /// use alloc::string::ToString;
1577 ///
1578 /// use xwrust::xwtm;
1579 /// use xwrust::xwmd::xwmq::*;
1580 ///
1581 /// static MQ: Xwmq<16, String> = Xwmq::new();
1582 ///
1583 /// pub fn xwrust_example_xwmq() {
1584 /// let (tx, rx) = MQ.init();
1585 /// // ...省略...
1586 /// let rc = rx.rq_to(xwtm::ft(xwtm::s(1)));
1587 /// match rc {
1588 /// Ok(d) => { // d是Box<String>
1589 /// },
1590 /// Err(e) => { // e是错误码
1591 /// },
1592 /// };
1593 /// // ...省略...
1594 /// }
1595 /// ```
1596 ///
1597 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1598 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1599 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1600 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1601 pub fn rq_to(&self, to: XwTm) -> Result<Box<T>, XwmqError> {
1602 unsafe {
1603 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1604 if rc == 0 {
1605 let mut topic = 0;
1606 let mut raw: *mut c_void = ptr::null_mut();
1607 rc = xwmq_rq_to(self.xwmq.mq.get(), &mut topic, &mut raw, to);
1608 xwmq_put(self.xwmq.mq.get());
1609 if XWOK == rc {
1610 let boxdata = Box::from_raw(raw as *mut T);
1611 Ok(boxdata)
1612 } else if -EINTR == rc {
1613 Err(XwmqError::Interrupt(rc))
1614 } else if -ETIMEDOUT == rc {
1615 Err(XwmqError::Timedout(rc))
1616 } else if -ENOTTHDCTX == rc {
1617 Err(XwmqError::NotThreadContext(rc))
1618 } else if -EDISPMPT == rc {
1619 Err(XwmqError::DisPmpt(rc))
1620 } else if -EDISBH == rc {
1621 Err(XwmqError::DisBh(rc))
1622 } else if -EDISIRQ == rc {
1623 Err(XwmqError::DisIrq(rc))
1624 } else {
1625 Err(XwmqError::Unknown(rc))
1626 }
1627 } else {
1628 Err(XwmqError::NotInit(rc))
1629 }
1630 }
1631 }
1632
1633 /// 等待从消息队列 **尾端** 接收一条消息,且等待不可被中断
1634 ///
1635 /// + 从消息队列的 **尾端** 取出消息,称为 **反向离队** 。
1636 /// + 当消息队列中没有消息时,接收线程会阻塞等待。
1637 /// + 接收线程的阻塞等待不可被中断。
1638 /// + 当消息队列中有可用的消息时,接收线程被唤醒,并取走一个消息,释放消息槽。
1639 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1640 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1641 ///
1642 /// # 上下文
1643 ///
1644 /// + 线程
1645 ///
1646 /// # 错误码
1647 ///
1648 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1649 /// + [`XwmqError::NotThreadContext`] 不在线程上下文内
1650 /// + [`XwmqError::DisPmpt`] 抢占被关闭
1651 /// + [`XwmqError::DisBh`] 中断底半部被关闭
1652 /// + [`XwmqError::DisIrq`] 中断被关闭
1653 ///
1654 /// # 示例
1655 ///
1656 /// ```rust
1657 /// extern crate alloc;
1658 /// use alloc::string::String;
1659 /// use alloc::string::ToString;
1660 ///
1661 /// use xwrust::xwmd::xwmq::*;
1662 ///
1663 /// static MQ: Xwmq<16, String> = Xwmq::new();
1664 ///
1665 /// pub fn xwrust_example_xwmq() {
1666 /// let (tx, rx) = MQ.init();
1667 /// // ...省略...
1668 /// let rc = rx.rq();
1669 /// match rc {
1670 /// Ok(d) => { // d是Box<String>
1671 /// },
1672 /// Err(e) => { // e是错误码
1673 /// },
1674 /// };
1675 /// // ...省略...
1676 /// }
1677 /// ```
1678 ///
1679 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1680 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1681 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1682 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1683 pub fn rq_unintr(&self) -> Result<Box<T>, XwmqError> {
1684 unsafe {
1685 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1686 if rc == 0 {
1687 let mut topic = 0;
1688 let mut raw: *mut c_void = ptr::null_mut();
1689 rc = xwmq_rq_unintr(self.xwmq.mq.get(), &mut topic, &mut raw);
1690 xwmq_put(self.xwmq.mq.get());
1691 if XWOK == rc {
1692 let boxdata = Box::from_raw(raw as *mut T);
1693 Ok(boxdata)
1694 } else if -ENOTTHDCTX == rc {
1695 Err(XwmqError::NotThreadContext(rc))
1696 } else if -EDISPMPT == rc {
1697 Err(XwmqError::DisPmpt(rc))
1698 } else if -EDISBH == rc {
1699 Err(XwmqError::DisBh(rc))
1700 } else if -EDISIRQ == rc {
1701 Err(XwmqError::DisIrq(rc))
1702 } else {
1703 Err(XwmqError::Unknown(rc))
1704 }
1705 } else {
1706 Err(XwmqError::NotInit(rc))
1707 }
1708 }
1709 }
1710
1711 /// 尝试从消息队列 **尾端** 接收一条消息
1712 ///
1713 /// + 从消息队列的 **尾端** 取出消息,称为 **反向离队** 。
1714 /// + 当消息队列中没有消息时,立即通过 [`Err()`] 返回 [`XwmqError::NoMsg`] 。
1715 /// + 当消息队列中有可用的消息时,会取走一个消息,并释放消息槽。
1716 /// 若有发送线程正在等待消息槽,将唤醒发送线程。
1717 /// + 消息 **离队** 时,会通过 [`Box::from_raw()`] 将数据重新放入 [`Box`] 中,然后通过 [`Ok()`] 返回。
1718 ///
1719 /// # 上下文
1720 ///
1721 /// + 任意
1722 ///
1723 /// # 错误码
1724 ///
1725 /// + [`XwmqError::NotInit`] 消息队列没有初始化
1726 /// + [`XwmqError::NoMsg`] 消息队列中没有消息
1727 ///
1728 /// # 示例
1729 ///
1730 /// ```rust
1731 /// extern crate alloc;
1732 /// use alloc::string::String;
1733 /// use alloc::string::ToString;
1734 ///
1735 /// use xwrust::xwmd::xwmq::*;
1736 ///
1737 /// static MQ: Xwmq<16, String> = Xwmq::new();
1738 ///
1739 /// pub fn xwrust_example_xwmq() {
1740 /// let (tx, rx) = MQ.init();
1741 /// // ...省略...
1742 /// let rc = rx.tryrq();
1743 /// match rc {
1744 /// Ok(d) => { // d是Box<String>
1745 /// },
1746 /// Err(e) => { // e是错误码
1747 /// },
1748 /// };
1749 /// // ...省略...
1750 /// }
1751 /// ```
1752 ///
1753 /// [`Box`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
1754 /// [`Box::from_raw()`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html#method.from_raw>
1755 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1756 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1757 pub fn tryrq(&self) -> Result<Box<T>, XwmqError> {
1758 unsafe {
1759 let mut rc = xwrustffi_xwmq_acquire(self.xwmq.mq.get(), *self.xwmq.tik.get());
1760 if rc == 0 {
1761 let mut topic = 0;
1762 let mut raw: *mut c_void = ptr::null_mut();
1763 rc = xwmq_tryrq(self.xwmq.mq.get(), &mut topic, &mut raw);
1764 xwmq_put(self.xwmq.mq.get());
1765 if XWOK == rc {
1766 let boxdata = Box::from_raw(raw as *mut T);
1767 Ok(boxdata)
1768 } else if -ENODATA == rc {
1769 Err(XwmqError::NoMsg(rc))
1770 } else {
1771 Err(XwmqError::Unknown(rc))
1772 }
1773 } else {
1774 Err(XwmqError::NotInit(rc))
1775 }
1776 }
1777 }
1778}