Skip to main content

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}