Skip to main content

xwrust/xwmd/
xwcq.rs

1//! XWOS RUST:循环队列
2//! ========
3//!
4//! XWOS RUST的 **循环队列** 是不依赖任何动态内存申请与释放的多线程间通讯机制。
5//!
6//! 循环队列有 `N` 个数据槽,每个数据槽的大小固定为 `S` 。
7//! 在创建循环队列时,需要指明类型常数 `S` 和 `N`,其内存完全在编译期进行分配。
8//!
9//! 发送时,可以将数据发送到队列后面(入队),也可以将数据发送到队列前面(插队)。
10//! 如果循环队列已满,不会阻塞发送者,循环队列会丢弃一份数据,腾出数据槽,再将新数据放入队列。
11//!
12//! 发送时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地被拷贝到循环队列的数据槽内的。
13//! 当发送的数据类型大小大于循环队列的数据槽大小 `S` ,发送会失败。
14//!
15//!
16//! 接收时,可以从循环队列的 **首端** 取出数据(首端离队),也可以从循环队列的 **尾端** 取出数据(尾端离队)。
17//! 还可以从循环队列的 **首端** 拷贝数据(首端拷贝),以及从循环队列的 **尾端** 拷贝数据(尾端拷贝)。
18//!
19//! 接收时,数据类型是泛型 `T` , `T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
20//! 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
21//!
22//!
23//! 循环队列的 **入队** 与 **首端离队** ,**插队** 与 **尾端离队** 分别组成了 **先进先出(FIFO)** 的关系。
24//!
25//!
26//! 由于不使用动态内存申请,又无法预测各个线程的生命周期,因此循环队列只能被定义为 [`static`] 限定的全局变量。
27//!
28//!
29//! 与 [`std::sync::mpsc`] 不同,循环队列不区分发送者与接收者,任何线程都可以发送与接收。
30//!
31//!
32//! # 创建
33//!
34//! XWOS RUST的循环队列可使用 [`Xwcq::new()`] 创建。创建时需要指定两个常量参数:数据槽的大小 `S` 以及数量 `N` 。
35//! 循环队列只能创建为具有静态生命周期 [`static`] 约束的全局变量:
36//!
37//! ```rust
38//! use xwrust::xwmd::xwcq::*;
39//!
40//! static CQ: Xwcq<64, 16> = Xwcq::new(); // 数据槽大小 `S` = 64; 数量 `N` = 16
41//! ```
42//!
43//!
44//! # 初始化
45//!
46//! 使用前,必须调用 [`Xwcq::init()`] 对循环队列进行初始化。如果创建循环队列时的常量参数不合适,初始化将以错误码返回。
47//!
48//! ```rust
49//! pub fn xwrust_example_xwcq() {
50//!     let rc = CQ.init();
51//! }
52//! ```
53//!
54//!
55//! # 发送
56//!
57//! 发送不会阻塞发送者,因此可在任意上下文进行发送。
58//!
59//! ### 入队
60//!
61//! **入队 (EnQueue)** [`Xwcq::eq`] 是指将数据发送到循环队列最后面。
62//!
63//! ### 插队
64//!
65//! **插队 (Jump the Queue)** [`Xwcq::jq`] 是指将数据发送到循环队列最前面。
66//!
67//!
68//! # 接收
69//!
70//! ### 首端离队
71//!
72//! 首端离队是指从循环队列的 **首端** 取出数据。取出数据后,数据槽被释放。
73//!
74//! + [`Xwcq::dq()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出或被中断。
75//! + [`Xwcq::dq_to()`] 若循环队列中为空,接收线程就限时阻塞等待,直到循环队列中有数据可取出或被中断或等待超时。
76//! + [`Xwcq::dq_unintr()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出。阻塞等待不可被中断。
77//! + [`Xwcq::trydq()`] 若循环队列中为空,就立即返回,可在中断中使用。
78//!
79//! ### 尾端离队
80//!
81//! 尾端离队是指从循环队列的 **尾端** 取出数据。取出数据后,数据槽被释放。
82//!
83//! + [`Xwcq::rq()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出或被中断。
84//! + [`Xwcq::rq_to()`] 若循环队列中为空,接收线程就限时阻塞等待,直到循环队列中有数据可取出或被中断或等待超时。
85//! + [`Xwcq::rq_unintr()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出。阻塞等待不可被中断。
86//! + [`Xwcq::tryrq()`] 若循环队列中为空,就立即返回,可在中断中使用。
87//!
88//! ### 首端拷贝
89//!
90//! 从循环队列 **首端** 拷贝数据时,数据不会取走数据,数据槽不会被释放。因此命名为 **前向窥视 (Peek at the Front of Queue)** 。
91//!
92//! + [`Xwcq::pfq()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出或被中断。
93//! + [`Xwcq::pfq_to()`] 若循环队列中为空,接收线程就限时阻塞等待,直到循环队列中有数据可取出或被中断或等待超时。
94//! + [`Xwcq::pfq_unintr()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出。阻塞等待不可被中断。
95//! + [`Xwcq::trypfq()`] 若循环队列中为空,就立即返回,可在中断中使用。
96//!
97//! ### 尾端拷贝
98//!
99//! 从循环队列 **尾端** 拷贝数据,数据不会取走数据,数据槽不会被释放。因此命名为 **后向窥视 (Peek at the Rear of Queue)** 。
100//!
101//! + [`Xwcq::prq()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出或被中断。
102//! + [`Xwcq::prq_to()`] 若循环队列中为空,接收线程就限时阻塞等待,直到循环队列中有数据可取出或被中断或等待超时。
103//! + [`Xwcq::prq_unintr()`] 若循环队列中为空,接收线程就阻塞等待,直到循环队列中有数据可取出。阻塞等待不可被中断。
104//! + [`Xwcq::tryprq()`] 若循环队列中为空,就立即返回,可在中断中使用。
105//!
106//!
107//! # 清空循环队列
108//!
109//! [`Xwcq::flush()`] 可将循环队列的所有数据槽清空。
110//!
111//!
112//! # 获取循环队列容量
113//!
114//! [`Xwcq::capacity()`] 可获取循环队列的数据槽的数量 `N` 。
115//!
116//!
117//! # 获取循环队列数据槽的大小
118//!
119//! [`Xwcq::size()`] 可获取循环队列数据槽的大小 `S` ,若 `S` 不满足内存对齐的要求,会自动向上调整。
120//!
121//!
122//! # 获取循环队列中有效数据槽的数量
123//!
124//! [`Xwcq::availability()`] 可获取循环队列中有效数据槽的数量。有效数据槽是指包含了可被接收数据的数据槽。
125//!
126//!
127//! # 示例
128//!
129//! [XWOS/xwam/xwrust-example/xwrust_example_xwcq](https://gitee.com/xwos/XWOS/blob/main/xwam/xwrust-example/xwrust_example_xwcq/src/lib.rs)
130//!
131//! [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
132//! [`static`]: <https://doc.rust-lang.org/std/keyword.static.html>
133//! [`std::sync::mpsc`]: <https://doc.rust-lang.org/std/sync/mpsc/index.html>
134
135
136extern crate core;
137use core::ffi::*;
138use core::result::Result;
139use core::cell::UnsafeCell;
140use core::mem;
141
142use crate::cfg::*;
143use crate::types::*;
144use crate::errno::*;
145
146
147extern "C" {
148    fn xwcq_init(cq: *mut XwmdXwcq,
149                 slotsize: XwSz, slotnum: XwSz,
150                 txq: *mut c_void) -> XwEr;
151    fn xwcq_fini(cq: *mut XwmdXwcq) -> XwEr;
152    fn xwcq_grab(cq: *mut XwmdXwcq) -> XwEr;
153    fn xwcq_put(cq: *mut XwmdXwcq) -> XwEr;
154    fn xwcq_get_tik(cq: *mut XwmdXwcq) -> XwSq;
155    fn xwrustffi_xwcq_acquire(cq: *mut XwmdXwcq, tik: XwSq) -> XwEr;
156    fn xwrustffi_xwcq_release(cq: *mut XwmdXwcq, tik: XwSq) -> XwEr;
157    fn xwcq_eq(cq: *mut XwmdXwcq, data: *const u8, size: *mut XwSz) -> XwEr;
158    fn xwcq_jq(cq: *mut XwmdXwcq, data: *const u8, size: *mut XwSz) -> XwEr;
159    fn xwcq_dq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
160    fn xwcq_dq_to(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz, to: XwTm) -> XwEr;
161    fn xwcq_dq_unintr(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
162    fn xwcq_trydq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
163    fn xwcq_rq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
164    fn xwcq_rq_to(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz, to: XwTm) -> XwEr;
165    fn xwcq_rq_unintr(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
166    fn xwcq_tryrq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
167    fn xwcq_pfq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
168    fn xwcq_pfq_to(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz, to: XwTm) -> XwEr;
169    fn xwcq_pfq_unintr(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
170    fn xwcq_trypfq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
171    fn xwcq_prq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
172    fn xwcq_prq_to(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz, to: XwTm) -> XwEr;
173    fn xwcq_prq_unintr(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
174    fn xwcq_tryprq(cq: *mut XwmdXwcq, data: *mut u8, size: *mut XwSz) -> XwEr;
175    fn xwcq_flush(cq: *mut XwmdXwcq) -> XwEr;
176    fn xwcq_get_capacity(cq: *mut XwmdXwcq, capbuf: *mut XwSz) -> XwEr;
177    fn xwcq_get_size(cq: *mut XwmdXwcq, szbuf: *mut XwSz) -> XwEr;
178    fn xwcq_get_availability(cq: *mut XwmdXwcq, avbbuf: *mut XwSz) -> XwEr;
179    fn xwcq_bind(cq: *mut XwmdXwcq, sel: *mut c_void, pos: XwSq) -> XwEr;
180    fn xwcq_unbind(cq: *mut XwmdXwcq, sel: *mut c_void) -> XwEr;
181}
182
183/// 循环队列的错误码
184#[derive(Debug)]
185pub enum XwcqError {
186    /// 没有错误
187    Ok(XwEr),
188    /// 循环队列没有初始化
189    NotInit(XwEr),
190    /// 循环队列内存大小错误
191    PoolSize(XwEr),
192    /// 数据大小错误
193    DataSize(XwEr),
194    /// 等待被中断
195    Interrupt(XwEr),
196    /// 等待超时
197    Timedout(XwEr),
198    /// 不在线程上下文内
199    NotThreadContext(XwEr),
200    /// 抢占被关闭
201    DisPmpt(XwEr),
202    /// 中断底半部被关闭
203    DisBh(XwEr),
204    /// 中断被关闭
205    DisIrq(XwEr),
206    /// 循环队列中没有数据
207    NoData(XwEr),
208    /// 未知错误
209    Unknown(XwEr),
210}
211
212impl XwcqError {
213    /// 消费掉 `XwcqError` 自身,返回内部的错误码。
214    pub fn unwrap(self) -> XwEr {
215        match self {
216            Self::Ok(rc) => rc,
217            Self::NotInit(rc) => rc,
218            Self::PoolSize(rc) => rc,
219            Self::DataSize(rc) => rc,
220            Self::Interrupt(rc) => rc,
221            Self::Timedout(rc) => rc,
222            Self::NotThreadContext(rc) => rc,
223            Self::DisPmpt(rc) => rc,
224            Self::DisBh(rc) => rc,
225            Self::DisIrq(rc) => rc,
226            Self::NoData(rc) => rc,
227            Self::Unknown(rc) => rc,
228        }
229    }
230
231    /// 如果信号量的错误码是 [`XwcqError::Ok`] ,返回 `true` 。
232    pub const fn is_ok(&self) -> bool {
233        matches!(*self, Self::Ok(_))
234    }
235
236    /// 如果信号量的错误码不是 [`XwcqError::Ok`] ,返回 `true` 。
237    pub const fn is_err(&self) -> bool {
238        !self.is_ok()
239    }
240}
241
242const XWCQ_MM_ALIGN: XwSz = XWMMCFG_ALIGNMENT;
243const XWCQ_MM_MSK: XwSz = XWCQ_MM_ALIGN - 1;
244
245/// 循环队列对象占用的内存大小
246#[cfg(target_pointer_width = "32")]
247pub const SIZEOF_XWCQ: usize = 96;
248
249/// 循环队列对象占用的内存大小
250#[cfg(target_pointer_width = "64")]
251pub const SIZEOF_XWCQ: usize = 192;
252
253/// 用于构建循环队列的内存数组类型
254#[repr(C)]
255#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
256#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
257pub(crate) struct XwmdXwcq {
258    pub(crate) obj: [u8; SIZEOF_XWCQ],
259}
260
261/// 用于构建队列数据的内存池数组类型
262#[repr(C)]
263#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
264#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
265pub(crate) struct XwmdXwcqPool<const S: XwSz, const N: XwSz>
266where
267    [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]: Sized
268{
269    pub(crate) mem: [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N],
270}
271
272/// 循环队列对象结构体
273pub struct Xwcq<const S: XwSz, const N: XwSz>
274where
275    [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]: Sized
276{
277    /// 用于初始化循环队列对象的内存空间
278    pub(crate) cq: UnsafeCell<XwmdXwcq>,
279    /// 用于初始化数据池的内存空间
280    pub(crate) pool: UnsafeCell<XwmdXwcqPool<S, N>>,
281    /// 循环队列对象的标签
282    pub(crate) tik: UnsafeCell<XwSq>,
283}
284
285impl<const S: XwSz, const N: XwSz> !Send for Xwcq<S, N>
286where
287    [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]: Sized
288{}
289
290unsafe impl<const S: XwSz, const N: XwSz> Sync for Xwcq<S, N>
291where
292    [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]: Sized
293{}
294
295impl<const S: XwSz, const N: XwSz> Xwcq<S, N>
296where
297    [u8; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]: Sized
298{
299    /// 新建循环队列对象
300    ///
301    /// 新建时需要指定类型常量参数。
302    ///
303    /// + `S` 是数据槽的大小,不能为0,若 `S` 不满足内存对齐的要求,会自动向上调整。
304    /// + `N` 是数据槽的数量,不能为0。
305    ///
306    /// 此方法是编译期方法。循环队列只可被定义为具有 [`'static`] 约束的全局变量全局变量:
307    ///
308    /// ```rust
309    /// use xwrust::xwmd::xwcq::*;
310    ///
311    /// static CQ: Xwcq<64, 8> = Xwcq::new(); // 64字节 * 8个槽
312    /// ```
313    ///
314    /// [`'static`]: https://doc.rust-lang.org/std/keyword.static.html
315    pub const fn new() -> Self {
316        Self {
317            cq: UnsafeCell::new(XwmdXwcq { obj: [0; SIZEOF_XWCQ] }),
318            pool: UnsafeCell::new(XwmdXwcqPool {
319                mem: [0; ((S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)) * N]
320            }),
321            tik: UnsafeCell::new(0),
322        }
323    }
324
325    /// 初始化循环队列对象
326    ///
327    /// 循环队列对象必须调用此方法一次,方可正常使用。
328    ///
329    /// 如果在创建循环队列时,指定的 `S * N == 0` ,初始化时将返回错误 [`XwcqError::PoolSize`] 。
330    ///
331    /// # 错误码
332    ///
333    /// + [`XwcqError::Ok`] 没有错误
334    /// + [`XwcqError::PoolSize`] 循环队列内存大小错误
335    ///
336    /// # 上下文
337    ///
338    /// + 任意
339    ///
340    /// # 示例
341    ///
342    /// ```rust
343    /// use xwrust::xwmd::xwcq::*;
344    ///
345    /// static CQ: Xwcq<64, 8> = Xwcq::new(); // 64字节 * 8个槽
346    ///
347    /// pub fn xwrust_example_xwcq() {
348    ///     let rc = CQ.init();
349    /// }
350    /// ```
351    pub fn init(&'static self) -> XwcqError {
352        unsafe {
353            let slotsize: XwSz = (S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK);
354            let rc = xwcq_init(self.cq.get(), slotsize, N, self.pool.get() as _);
355            *self.tik.get() = xwcq_get_tik(self.cq.get());
356            if rc == 0 {
357                XwcqError::Ok(rc)
358            } else if rc == -ESIZE {
359                XwcqError::PoolSize(rc)
360            } else {
361                XwcqError::Unknown(rc)
362            }
363        }
364    }
365
366    /// 将数据发送到循环队列的 **尾端** (入队,EnQueue)
367    ///
368    /// + 如果循环队列数据已被填满,循环队列会循环回队列 **首端** 的位置,覆盖掉原数据。
369    /// + 发送时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地被拷贝到循环队列的数据槽内的。
370    /// + 当发送的数据类型大小大于循环队列的数据槽大小 `S` ,发送会失败,并返回错误码 [`XwcqError::DataSize`] 。
371    ///
372    /// # 参数说明
373    ///
374    /// + data: 类型为 `T` 的数据
375    ///
376    /// # 错误码
377    ///
378    /// + [`XwcqError::Ok`] 没有错误
379    /// + [`XwcqError::NotInit`] 循环队列没有初始化
380    /// + [`XwcqError::DataSize`] 数据大小错误
381    ///
382    /// # 上下文
383    ///
384    /// + 任意
385    ///
386    /// # 示例
387    ///
388    /// ```rust
389    /// use xwrust::xwos::thd::SThd;
390    /// use xwrust::xwmd::xwcq::*;
391    ///
392    /// static CQ: Xwcq<64, 16> = Xwcq::new();
393    /// static CHILD: SThd<1024, &str> = SThd::new("CHILD0", true);
394    ///
395    /// pub fn xwrust_example_xwcq() {
396    ///     CQ.init();
397    ///     CHILD.run(|_| { // 子线程0
398    ///             // 将utf-8字符串放入 `[u8; 64]` 数组中后发送
399    ///             let mut buffer: [u8; 64] = [0; 64];
400    ///             let msg = "子线程数据".as_bytes();
401    ///             let msgsize = msg.len();
402    ///             buffer[..msgsize].copy_from_slice(msg);
403    ///             let rc = CQ.eq(buffer);
404    ///             match rc {
405    ///                 Ok(sz) => { // 发送数据成功
406    ///                 },
407    ///                 Err(e) => { // 发送数据失败
408    ///                 },
409    ///             };
410    ///             "OK"
411    ///         });
412    /// }
413    /// ```
414    ///
415    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
416    pub fn eq<T>(&self, data: T) -> Result<XwSz, XwcqError>
417    where
418        T: Sized + Send
419    {
420        unsafe {
421            let mut datasz: XwSz = mem::size_of::<T>();
422            if datasz <= self.size() {
423                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
424                if rc == 0 {
425                    let refdata = &data as *const T;
426                    rc = xwcq_eq(self.cq.get(), refdata as *const u8, &mut datasz as _);
427                    xwcq_put(self.cq.get());
428                    if XWOK == rc {
429                        Ok(datasz)
430                    } else {
431                        Err(XwcqError::Unknown(rc))
432                    }
433                } else {
434                    Err(XwcqError::NotInit(rc))
435                }
436            } else {
437                Err(XwcqError::DataSize(-ESIZE))
438            }
439        }
440    }
441
442    /// 将数据发送循环队列的 **首端** (插队,Jump the Queue)
443    ///
444    /// + 如果循环队列数据已被填满,循环队列会循环回队列 **尾端** 的位置,覆盖掉原数据。
445    /// + 发送时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地被拷贝到循环队列的数据槽内的。
446    /// + 当发送的数据类型大小大于循环队列的数据槽大小 `S` ,发送会失败,并返回错误码 [`XwcqError::DataSize`] 。
447    ///
448    /// # 参数说明
449    ///
450    /// + data: 类型为 `T` 的数据
451    ///
452    /// # 错误码
453    ///
454    /// + [`XwcqError::Ok`] 没有错误
455    /// + [`XwcqError::NotInit`] 循环队列没有初始化
456    /// + [`XwcqError::DataSize`] 数据大小错误
457    ///
458    /// # 上下文
459    ///
460    /// + 任意
461    ///
462    /// # 示例
463    ///
464    /// ```rust
465    /// use xwrust::xwos::thd::SThd;
466    /// use xwrust::xwmd::xwcq::*;
467    ///
468    /// static CQ: Xwcq<64, 16> = Xwcq::new();
469    /// static CHILD: SThd<1024, &str> = SThd::new("CHILD0", true);
470    ///
471    /// pub fn xwrust_example_xwcq() {
472    ///     CQ.init();
473    ///     CHILD.run(|_| { // 子线程0
474    ///             // 将utf-8字符串放入 `[u8; 64]` 数组中后发送
475    ///             let mut buffer: [u8; 64] = [0; 64];
476    ///             let msg = "子线程数据".as_bytes();
477    ///             let msgsize = msg.len();
478    ///             buffer[..msgsize].copy_from_slice(msg);
479    ///             let rc = CQ.jq(buffer);
480    ///             match rc {
481    ///                 Ok(sz) => { // 发送数据成功
482    ///                 },
483    ///                 Err(e) => { // 发送数据失败
484    ///                 },
485    ///             };
486    ///             "OK"
487    ///         });
488    /// }
489    /// ```
490    ///
491    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
492    pub fn jq<T>(&self, data: T) -> Result<XwSz, XwcqError>
493    where
494        T: Sized + Send
495    {
496        unsafe {
497            let mut datasz: XwSz = mem::size_of::<T>();
498            if datasz <= self.size() {
499                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
500                if rc == 0 {
501                    let refdata = &data as *const T;
502                    rc = xwcq_jq(self.cq.get(), refdata as *const u8, &mut datasz as _);
503                    xwcq_put(self.cq.get());
504                    if XWOK == rc {
505                        Ok(datasz)
506                    } else {
507                        Err(XwcqError::Unknown(rc))
508                    }
509                } else {
510                    Err(XwcqError::NotInit(rc))
511                }
512            } else {
513                Err(XwcqError::DataSize(-ESIZE))
514            }
515        }
516    }
517
518    /// 等待从循环队列的 **首端** 接收数据(离队,DeQueue)
519    ///
520    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
521    /// + 若循环队列为空,线程会阻塞等待。
522    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
523    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
524    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
525    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
526    ///
527    /// # 上下文
528    ///
529    /// + 线程
530    ///
531    /// # 错误码
532    ///
533    /// + [`XwcqError::Ok`] 没有错误
534    /// + [`XwcqError::NotInit`] 循环队列没有初始化
535    /// + [`XwcqError::Interrupt`] 等待被中断
536    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
537    /// + [`XwcqError::DisPmpt`] 抢占被关闭
538    /// + [`XwcqError::DisBh`] 中断底半部被关闭
539    /// + [`XwcqError::DisIrq`] 中断被关闭
540    ///
541    /// # 示例
542    ///
543    /// ```rust
544    /// extern crate core;
545    /// use core::str;
546    /// use core::slice::memchr::memchr;
547    ///
548    /// use xwrust::xwmd::xwcq::*;
549    ///
550    /// static CQ: Xwcq<64, 16> = Xwcq::new();
551    ///
552    /// pub fn xwrust_example_xwcq() {
553    ///     CQ.init();
554    ///     // ...省略...
555    ///     let rc = CQ.dq::<[u8; 64]>();
556    ///     match rc {
557    ///         Ok(d) => { // 获取数据成功
558    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
559    ///             let totalslice = &d[0..64];
560    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
561    ///             let msgu8slice = &d[0..nullpos];
562    ///             let msg = str::from_utf8(msgu8slice);
563    ///         },
564    ///         Err(e) => { // 获取数据失败
565    ///             break;
566    ///         },
567    ///     };
568    /// }
569    /// ```
570    ///
571    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
572    pub fn dq<T>(&self) -> Result<T, XwcqError>
573    where
574        T: Sized + Send
575    {
576        unsafe {
577            let mut datasz: XwSz = mem::size_of::<T>();
578            if datasz <= self.size() {
579                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
580                if rc == 0 {
581                    let mut data: T = mem::zeroed();
582                    rc = xwcq_dq(self.cq.get(),
583                                 &mut data as *mut T as *mut u8, &mut datasz as _);
584                    xwcq_put(self.cq.get());
585                    if XWOK == rc {
586                        Ok(data)
587                    } else if  -EINTR == rc {
588                        Err(XwcqError::Interrupt(rc))
589                    } else if -ENOTTHDCTX == rc {
590                        Err(XwcqError::NotThreadContext(rc))
591                    } else if -EDISPMPT == rc {
592                        Err(XwcqError::DisPmpt(rc))
593                    } else if -EDISBH == rc {
594                        Err(XwcqError::DisBh(rc))
595                    } else if -EDISIRQ == rc {
596                        Err(XwcqError::DisIrq(rc))
597                    } else {
598                        Err(XwcqError::Unknown(rc))
599                    }
600                } else {
601                    Err(XwcqError::NotInit(rc))
602                }
603            } else {
604                Err(XwcqError::DataSize(-ESIZE))
605            }
606        }
607    }
608
609    /// 等待从循环队列的 **首端** 接收数据(离队,DeQueue)
610    ///
611    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
612    /// + 若循环队列为空,线程会阻塞等待,等待时会指定一个唤醒时间点。
613    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
614    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
615    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
616    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
617    /// + 当到达指定的唤醒时间点,线程被唤醒,返回错误码 [`XwcqError::Timedout`] 。
618    ///
619    /// # 参数说明
620    ///
621    /// + to: 期望唤醒的时间点
622    ///
623    /// # 上下文
624    ///
625    /// + 线程
626    ///
627    /// # 错误码
628    ///
629    /// + [`XwcqError::Ok`] 没有错误
630    /// + [`XwcqError::NotInit`] 循环队列没有初始化
631    /// + [`XwcqError::Interrupt`] 等待被中断
632    /// + [`XwcqError::Timedout`] 等待超时
633    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
634    /// + [`XwcqError::DisPmpt`] 抢占被关闭
635    /// + [`XwcqError::DisBh`] 中断底半部被关闭
636    /// + [`XwcqError::DisIrq`] 中断被关闭
637    ///
638    /// # 示例
639    ///
640    /// ```rust
641    /// extern crate core;
642    /// use core::str;
643    /// use core::slice::memchr::memchr;
644    ///
645    /// use xwrust::xwtm;
646    /// use xwrust::xwmd::xwcq::*;
647    ///
648    /// static CQ: Xwcq<64, 16> = Xwcq::new();
649    ///
650    /// pub fn xwrust_example_xwcq() {
651    ///     CQ.init();
652    ///     // ...省略...
653    ///     let rc = CQ.dq_to::<[u8; 64]>(xwtm::ft(xwtm::s(1)));
654    ///     match rc {
655    ///         Ok(d) => { // 获取数据成功
656    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
657    ///             let totalslice = &d[0..64];
658    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
659    ///             let msgu8slice = &d[0..nullpos];
660    ///             let msg = str::from_utf8(msgu8slice);
661    ///         },
662    ///         Err(e) => { // 获取数据失败
663    ///             break;
664    ///         },
665    ///     };
666    /// }
667    /// ```
668    ///
669    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
670    pub fn dq_to<T>(&self, to: XwTm) -> Result<T, XwcqError>
671    where
672        T: Sized + Send
673    {
674        unsafe {
675            let mut datasz: XwSz = mem::size_of::<T>();
676            if datasz <= self.size() {
677                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
678                if rc == 0 {
679                    let mut data: T = mem::zeroed();
680                    rc = xwcq_dq_to(self.cq.get(),
681                                    &mut data as *mut T as *mut u8, &mut datasz as _,
682                                    to);
683                    xwcq_put(self.cq.get());
684                    if XWOK == rc {
685                        Ok(data)
686                    } else if  -EINTR == rc {
687                        Err(XwcqError::Interrupt(rc))
688                    } else if -ETIMEDOUT == rc {
689                        Err(XwcqError::Timedout(rc))
690                    } else if -ENOTTHDCTX == rc {
691                        Err(XwcqError::NotThreadContext(rc))
692                    } else if -EDISPMPT == rc {
693                        Err(XwcqError::DisPmpt(rc))
694                    } else if -EDISBH == rc {
695                        Err(XwcqError::DisBh(rc))
696                    } else if -EDISIRQ == rc {
697                        Err(XwcqError::DisIrq(rc))
698                    } else {
699                        Err(XwcqError::Unknown(rc))
700                    }
701                } else {
702                    Err(XwcqError::NotInit(rc))
703                }
704            } else {
705                Err(XwcqError::DataSize(-ESIZE))
706            }
707        }
708    }
709
710    /// 等待从循环队列的 **首端** 接收数据(离队,DeQueue),并且等待不可被中断
711    ///
712    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
713    /// + 若循环队列为空,线程会阻塞等待,且不可被中断。
714    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
715    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
716    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
717    ///
718    /// # 上下文
719    ///
720    /// + 线程
721    ///
722    /// # 错误码
723    ///
724    /// + [`XwcqError::Ok`] 没有错误
725    /// + [`XwcqError::NotInit`] 循环队列没有初始化
726    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
727    /// + [`XwcqError::DisPmpt`] 抢占被关闭
728    /// + [`XwcqError::DisBh`] 中断底半部被关闭
729    /// + [`XwcqError::DisIrq`] 中断被关闭
730    ///
731    /// # 示例
732    ///
733    /// ```rust
734    /// extern crate core;
735    /// use core::str;
736    /// use core::slice::memchr::memchr;
737    ///
738    /// use xwrust::xwmd::xwcq::*;
739    ///
740    /// static CQ: Xwcq<64, 16> = Xwcq::new();
741    ///
742    /// pub fn xwrust_example_xwcq() {
743    ///     CQ.init();
744    ///     // ...省略...
745    ///     let rc = CQ.dq_unintr::<[u8; 64]>();
746    ///     match rc {
747    ///         Ok(d) => { // 获取数据成功
748    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
749    ///             let totalslice = &d[0..64];
750    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
751    ///             let msgu8slice = &d[0..nullpos];
752    ///             let msg = str::from_utf8(msgu8slice);
753    ///         },
754    ///         Err(e) => { // 获取数据失败
755    ///             break;
756    ///         },
757    ///     };
758    /// }
759    /// ```
760    ///
761    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
762    pub fn dq_unintr<T>(&self) -> Result<T, XwcqError>
763    where
764        T: Sized + Send
765    {
766        unsafe {
767            let mut datasz: XwSz = mem::size_of::<T>();
768            if datasz <= self.size() {
769                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
770                if rc == 0 {
771                    let mut data: T = mem::zeroed();
772                    rc = xwcq_dq_unintr(self.cq.get(),
773                                        &mut data as *mut T as *mut u8,
774                                        &mut datasz as _);
775                    xwcq_put(self.cq.get());
776                    if XWOK == rc {
777                        Ok(data)
778                    } else if -ENOTTHDCTX == rc {
779                        Err(XwcqError::NotThreadContext(rc))
780                    } else if -EDISPMPT == rc {
781                        Err(XwcqError::DisPmpt(rc))
782                    } else if -EDISBH == rc {
783                        Err(XwcqError::DisBh(rc))
784                    } else if -EDISIRQ == rc {
785                        Err(XwcqError::DisIrq(rc))
786                    } else {
787                        Err(XwcqError::Unknown(rc))
788                    }
789                } else {
790                    Err(XwcqError::NotInit(rc))
791                }
792            } else {
793                Err(XwcqError::DataSize(-ESIZE))
794            }
795        }
796    }
797
798    /// 尝试从循环队列的 **首端** 接收数据(离队,DeQueue)
799    ///
800    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
801    /// + 若循环队列为空,立即返回 [`XwcqError::DataSize`] ,此方法不会阻塞等待。
802    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
803    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
804    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
805    ///
806    /// # 上下文
807    ///
808    /// + 任意
809    ///
810    /// # 错误码
811    ///
812    /// + [`XwcqError::Ok`] 没有错误
813    /// + [`XwcqError::NotInit`] 循环队列没有初始化
814    /// + [`XwcqError::NoData`] 循环队列中没有数据
815    ///
816    /// # 示例
817    ///
818    /// ```rust
819    /// extern crate core;
820    /// use core::str;
821    /// use core::slice::memchr::memchr;
822    ///
823    /// use xwrust::xwmd::xwcq::*;
824    ///
825    /// static CQ: Xwcq<64, 16> = Xwcq::new();
826    ///
827    /// pub fn xwrust_example_xwcq() {
828    ///     CQ.init();
829    ///     // ...省略...
830    ///     let rc = CQ.trydq::<[u8; 64]>();
831    ///     match rc {
832    ///         Ok(d) => { // 获取数据成功
833    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
834    ///             let totalslice = &d[0..64];
835    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
836    ///             let msgu8slice = &d[0..nullpos];
837    ///             let msg = str::from_utf8(msgu8slice);
838    ///         },
839    ///         Err(e) => { // 获取数据失败
840    ///         },
841    ///     };
842    /// }
843    /// ```
844    ///
845    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
846    pub fn trydq<T>(&self) -> Result<T, XwcqError>
847    where
848        T: Sized + Send
849    {
850        unsafe {
851            let mut datasz: XwSz = mem::size_of::<T>();
852            if datasz <= self.size() {
853                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
854                if rc == 0 {
855                    let mut data: T = mem::zeroed();
856                    rc = xwcq_trydq(self.cq.get(),
857                                    &mut data as *mut T as *mut u8, &mut datasz as _);
858                    xwcq_put(self.cq.get());
859                    if XWOK == rc {
860                        Ok(data)
861                    } else if -ENODATA == rc {
862                        Err(XwcqError::NoData(rc))
863                    } else {
864                        Err(XwcqError::Unknown(rc))
865                    }
866                } else {
867                    Err(XwcqError::NotInit(rc))
868                }
869            } else {
870                Err(XwcqError::DataSize(-ESIZE))
871            }
872        }
873    }
874
875    /// 等待从循环队列的 **尾端** 接收数据(反向离队,Reversely deQueue)
876    ///
877    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
878    /// + 若循环队列为空,线程会阻塞等待。
879    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
880    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
881    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
882    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
883    ///
884    /// # 上下文
885    ///
886    /// + 线程
887    ///
888    /// # 错误码
889    ///
890    /// + [`XwcqError::Ok`] 没有错误
891    /// + [`XwcqError::NotInit`] 循环队列没有初始化
892    /// + [`XwcqError::Interrupt`] 等待被中断
893    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
894    /// + [`XwcqError::DisPmpt`] 抢占被关闭
895    /// + [`XwcqError::DisBh`] 中断底半部被关闭
896    /// + [`XwcqError::DisIrq`] 中断被关闭
897    ///
898    /// # 示例
899    ///
900    /// ```rust
901    /// extern crate core;
902    /// use core::str;
903    /// use core::slice::memchr::memchr;
904    ///
905    /// use xwrust::xwmd::xwcq::*;
906    ///
907    /// static CQ: Xwcq<64, 16> = Xwcq::new();
908    ///
909    /// pub fn xwrust_example_xwcq() {
910    ///     CQ.init();
911    ///     // ...省略...
912    ///     let rc = CQ.rq::<[u8; 64]>();
913    ///     match rc {
914    ///         Ok(d) => { // 获取数据成功
915    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
916    ///             let totalslice = &d[0..64];
917    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
918    ///             let msgu8slice = &d[0..nullpos];
919    ///             let msg = str::from_utf8(msgu8slice);
920    ///         },
921    ///         Err(e) => { // 获取数据失败
922    ///             break;
923    ///         },
924    ///     };
925    /// }
926    /// ```
927    ///
928    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
929    pub fn rq<T>(&self) -> Result<T, XwcqError>
930    where
931        T: Sized + Send
932    {
933        unsafe {
934            let mut datasz: XwSz = mem::size_of::<T>();
935            if datasz <= self.size() {
936                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
937                if rc == 0 {
938                    let mut data: T = mem::zeroed();
939                    rc = xwcq_rq(self.cq.get(),
940                                 &mut data as *mut T as *mut u8, &mut datasz as _);
941                    xwcq_put(self.cq.get());
942                    if XWOK == rc {
943                        Ok(data)
944                    } else if  -EINTR == rc {
945                        Err(XwcqError::Interrupt(rc))
946                    } else if -ENOTTHDCTX == rc {
947                        Err(XwcqError::NotThreadContext(rc))
948                    } else if -EDISPMPT == rc {
949                        Err(XwcqError::DisPmpt(rc))
950                    } else if -EDISBH == rc {
951                        Err(XwcqError::DisBh(rc))
952                    } else if -EDISIRQ == rc {
953                        Err(XwcqError::DisIrq(rc))
954                    } else {
955                        Err(XwcqError::Unknown(rc))
956                    }
957                } else {
958                    Err(XwcqError::NotInit(rc))
959                }
960            } else {
961                Err(XwcqError::DataSize(-ESIZE))
962            }
963        }
964    }
965
966    /// 限时等待从循环队列的 **尾端** 接收数据(反向离队,Reversely deQueue)
967    ///
968    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
969    /// + 若循环队列为空,线程会阻塞等待,等待时会指定一个唤醒时间点。
970    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
971    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
972    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
973    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
974    /// + 当到达指定的唤醒时间点,线程被唤醒,返回错误码 [`XwcqError::Timedout`] 。
975    ///
976    /// # 参数说明
977    ///
978    /// + to: 期望唤醒的时间点
979    ///
980    /// # 上下文
981    ///
982    /// + 线程
983    ///
984    /// # 错误码
985    ///
986    /// + [`XwcqError::Ok`] 没有错误
987    /// + [`XwcqError::NotInit`] 循环队列没有初始化
988    /// + [`XwcqError::Interrupt`] 等待被中断
989    /// + [`XwcqError::Timedout`] 等待超时
990    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
991    /// + [`XwcqError::DisPmpt`] 抢占被关闭
992    /// + [`XwcqError::DisBh`] 中断底半部被关闭
993    /// + [`XwcqError::DisIrq`] 中断被关闭
994    ///
995    /// # 上下文
996    ///
997    /// + 线程
998    ///
999    /// # 示例
1000    ///
1001    /// ```rust
1002    /// extern crate core;
1003    /// use core::str;
1004    /// use core::slice::memchr::memchr;
1005    ///
1006    /// use xwrust::xwtm;
1007    /// use xwrust::xwmd::xwcq::*;
1008    ///
1009    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1010    ///
1011    /// pub fn xwrust_example_xwcq() {
1012    ///     CQ.init();
1013    ///     // ...省略...
1014    ///     let rc = CQ.rq_to::<[u8; 64]>(xwtm::ft(xwtm::s(1)));
1015    ///     match rc {
1016    ///         Ok(d) => { // 获取数据成功
1017    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1018    ///             let totalslice = &d[0..64];
1019    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1020    ///             let msgu8slice = &d[0..nullpos];
1021    ///             let msg = str::from_utf8(msgu8slice);
1022    ///         },
1023    ///         Err(e) => { // 获取数据失败
1024    ///             break;
1025    ///         },
1026    ///     };
1027    /// }
1028    /// ```
1029    ///
1030    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1031    pub fn rq_to<T>(&self, to: XwTm) -> Result<T, XwcqError>
1032    where
1033        T: Sized + Send
1034    {
1035        unsafe {
1036            let mut datasz: XwSz = mem::size_of::<T>();
1037            if datasz <= self.size() {
1038                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1039                if rc == 0 {
1040                    let mut data: T = mem::zeroed();
1041                    rc = xwcq_rq_to(self.cq.get(),
1042                                    &mut data as *mut T as *mut u8, &mut datasz as _,
1043                                    to);
1044                    xwcq_put(self.cq.get());
1045                    if XWOK == rc {
1046                        Ok(data)
1047                    } else if  -EINTR == rc {
1048                        Err(XwcqError::Interrupt(rc))
1049                    } else if -ETIMEDOUT == rc {
1050                        Err(XwcqError::Timedout(rc))
1051                    } else if -ENOTTHDCTX == rc {
1052                        Err(XwcqError::NotThreadContext(rc))
1053                    } else if -EDISPMPT == rc {
1054                        Err(XwcqError::DisPmpt(rc))
1055                    } else if -EDISBH == rc {
1056                        Err(XwcqError::DisBh(rc))
1057                    } else if -EDISIRQ == rc {
1058                        Err(XwcqError::DisIrq(rc))
1059                    } else {
1060                        Err(XwcqError::Unknown(rc))
1061                    }
1062                } else {
1063                    Err(XwcqError::NotInit(rc))
1064                }
1065            } else {
1066                Err(XwcqError::DataSize(-ESIZE))
1067            }
1068        }
1069    }
1070
1071    /// 等待从循环队列的 **尾端** 接收数据(反向离队,Reversely deQueue),并且等待不可被中断
1072    ///
1073    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1074    /// + 若循环队列为空,线程会阻塞等待,且不可被中断。
1075    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1076    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1077    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1078    ///
1079    /// # 上下文
1080    ///
1081    /// + 线程
1082    ///
1083    /// # 错误码
1084    ///
1085    /// + [`XwcqError::Ok`] 没有错误
1086    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1087    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1088    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1089    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1090    /// + [`XwcqError::DisIrq`] 中断被关闭
1091    ///
1092    /// # 示例
1093    ///
1094    /// ```rust
1095    /// extern crate core;
1096    /// use core::str;
1097    /// use core::slice::memchr::memchr;
1098    ///
1099    /// use xwrust::xwmd::xwcq::*;
1100    ///
1101    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1102    ///
1103    /// pub fn xwrust_example_xwcq() {
1104    ///     CQ.init();
1105    ///     // ...省略...
1106    ///     let rc = CQ.rq_unintr::<[u8; 64]>();
1107    ///     match rc {
1108    ///         Ok(d) => { // 获取数据成功
1109    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1110    ///             let totalslice = &d[0..64];
1111    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1112    ///             let msgu8slice = &d[0..nullpos];
1113    ///             let msg = str::from_utf8(msgu8slice);
1114    ///         },
1115    ///         Err(e) => { // 获取数据失败
1116    ///             break;
1117    ///         },
1118    ///     };
1119    /// }
1120    /// ```
1121    ///
1122    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1123    pub fn rq_unintr<T>(&self) -> Result<T, XwcqError>
1124    where
1125        T: Sized + Send
1126    {
1127        unsafe {
1128            let mut datasz: XwSz = mem::size_of::<T>();
1129            if datasz <= self.size() {
1130                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1131                if rc == 0 {
1132                    let mut data: T = mem::zeroed();
1133                    rc = xwcq_rq_unintr(self.cq.get(),
1134                                        &mut data as *mut T as *mut u8,
1135                                        &mut datasz as _);
1136                    xwcq_put(self.cq.get());
1137                    if XWOK == rc {
1138                        Ok(data)
1139                    } else if -ENOTTHDCTX == rc {
1140                        Err(XwcqError::NotThreadContext(rc))
1141                    } else if -EDISPMPT == rc {
1142                        Err(XwcqError::DisPmpt(rc))
1143                    } else if -EDISBH == rc {
1144                        Err(XwcqError::DisBh(rc))
1145                    } else if -EDISIRQ == rc {
1146                        Err(XwcqError::DisIrq(rc))
1147                    } else {
1148                        Err(XwcqError::Unknown(rc))
1149                    }
1150                } else {
1151                    Err(XwcqError::NotInit(rc))
1152                }
1153            } else {
1154                Err(XwcqError::DataSize(-ESIZE))
1155            }
1156        }
1157    }
1158
1159    /// 尝试从循环队列的 **尾端** 接收数据(反向离队,Reversely deQueue)
1160    ///
1161    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1162    /// + 若循环队列为空,立即返回 [`XwcqError::DataSize`] ,此方法不会阻塞。
1163    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1164    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1165    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1166    ///
1167    /// # 上下文
1168    ///
1169    /// + 任意
1170    ///
1171    /// # 错误码
1172    ///
1173    /// + [`XwcqError::Ok`] 没有错误
1174    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1175    /// + [`XwcqError::NoData`] 循环队列中没有数据
1176    ///
1177    /// # 示例
1178    ///
1179    /// ```rust
1180    /// extern crate core;
1181    /// use core::str;
1182    /// use core::slice::memchr::memchr;
1183    ///
1184    /// use xwrust::xwmd::xwcq::*;
1185    ///
1186    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1187    ///
1188    /// pub fn xwrust_example_xwcq() {
1189    ///     CQ.init();
1190    ///     // ...省略...
1191    ///     let rc = CQ.tryrq::<[u8; 64]>();
1192    ///     match rc {
1193    ///         Ok(d) => { // 获取数据成功
1194    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1195    ///             let totalslice = &d[0..64];
1196    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1197    ///             let msgu8slice = &d[0..nullpos];
1198    ///             let msg = str::from_utf8(msgu8slice);
1199    ///         },
1200    ///         Err(e) => { // 获取数据失败
1201    ///         },
1202    ///     };
1203    /// }
1204    /// ```
1205    ///
1206    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1207    pub fn tryrq<T>(&self) -> Result<T, XwcqError>
1208    where
1209        T: Sized + Send
1210    {
1211        unsafe {
1212            let mut datasz: XwSz = mem::size_of::<T>();
1213            if datasz <= self.size() {
1214                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1215                if rc == 0 {
1216                    let mut data: T = mem::zeroed();
1217                    rc = xwcq_tryrq(self.cq.get(),
1218                                    &mut data as *mut T as *mut u8, &mut datasz as _);
1219                    xwcq_put(self.cq.get());
1220                    if XWOK == rc {
1221                        Ok(data)
1222                    } else if -ENODATA == rc {
1223                        Err(XwcqError::NoData(rc))
1224                    } else {
1225                        Err(XwcqError::Unknown(rc))
1226                    }
1227                } else {
1228                    Err(XwcqError::NotInit(rc))
1229                }
1230            } else {
1231                Err(XwcqError::DataSize(-ESIZE))
1232            }
1233        }
1234    }
1235
1236    /// 等待从循环队列 **头端** 拷贝数据(Peek at the Front of Queue)
1237    ///
1238    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1239    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1240    /// + 若循环队列为空,线程会阻塞等待。
1241    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1242    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1243    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1244    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
1245    ///
1246    /// # 上下文
1247    ///
1248    /// + 线程
1249    ///
1250    /// # 错误码
1251    ///
1252    /// + [`XwcqError::Ok`] 没有错误
1253    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1254    /// + [`XwcqError::Interrupt`] 等待被中断
1255    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1256    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1257    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1258    /// + [`XwcqError::DisIrq`] 中断被关闭
1259    ///
1260    /// # 示例
1261    ///
1262    /// ```rust
1263    /// extern crate core;
1264    /// use core::str;
1265    /// use core::slice::memchr::memchr;
1266    ///
1267    /// use xwrust::xwmd::xwcq::*;
1268    ///
1269    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1270    ///
1271    /// pub fn xwrust_example_xwcq() {
1272    ///     CQ.init();
1273    ///     // ...省略...
1274    ///     let rc = CQ.pfq::<[u8; 64]>();
1275    ///     match rc {
1276    ///         Ok(d) => { // 获取数据成功
1277    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1278    ///             let totalslice = &d[0..64];
1279    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1280    ///             let msgu8slice = &d[0..nullpos];
1281    ///             let msg = str::from_utf8(msgu8slice);
1282    ///         },
1283    ///         Err(e) => { // 获取数据失败
1284    ///             break;
1285    ///         },
1286    ///     };
1287    /// }
1288    /// ```
1289    ///
1290    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1291    pub fn pfq<T>(&self) -> Result<T, XwcqError>
1292    where
1293        T: Sized + Send
1294    {
1295        unsafe {
1296            let mut datasz: XwSz = mem::size_of::<T>();
1297            if datasz <= self.size() {
1298                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1299                if rc == 0 {
1300                    let mut data: T = mem::zeroed();
1301                    rc = xwcq_pfq(self.cq.get(),
1302                                  &mut data as *mut T as *mut u8, &mut datasz as _);
1303                    xwcq_put(self.cq.get());
1304                    if XWOK == rc {
1305                        Ok(data)
1306                    } else if  -EINTR == rc {
1307                        Err(XwcqError::Interrupt(rc))
1308                    } else if -ENOTTHDCTX == rc {
1309                        Err(XwcqError::NotThreadContext(rc))
1310                    } else if -EDISPMPT == rc {
1311                        Err(XwcqError::DisPmpt(rc))
1312                    } else if -EDISBH == rc {
1313                        Err(XwcqError::DisBh(rc))
1314                    } else if -EDISIRQ == rc {
1315                        Err(XwcqError::DisIrq(rc))
1316                    } else {
1317                        Err(XwcqError::Unknown(rc))
1318                    }
1319                } else {
1320                    Err(XwcqError::NotInit(rc))
1321                }
1322            } else {
1323                Err(XwcqError::DataSize(-ESIZE))
1324            }
1325        }
1326    }
1327
1328    /// 限时等待从循环队列 **头端** 拷贝数据(Peek at the Front of Queue)
1329    ///
1330    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1331    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1332    /// + 若循环队列为空,线程会阻塞等待,等待时会指定一个唤醒时间点。
1333    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1334    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1335    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1336    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
1337    /// + 当到达指定的唤醒时间点,线程被唤醒,返回错误码 [`XwcqError::Timedout`] 。
1338    ///
1339    /// # 参数说明
1340    ///
1341    /// + to: 期望唤醒的时间点
1342    ///
1343    /// # 上下文
1344    ///
1345    /// + 线程
1346    ///
1347    /// # 错误码
1348    ///
1349    /// + [`XwcqError::Ok`] 没有错误
1350    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1351    /// + [`XwcqError::Interrupt`] 等待被中断
1352    /// + [`XwcqError::Timedout`] 等待超时
1353    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1354    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1355    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1356    /// + [`XwcqError::DisIrq`] 中断被关闭
1357    ///
1358    /// # 示例
1359    ///
1360    /// ```rust
1361    /// extern crate core;
1362    /// use core::str;
1363    /// use core::slice::memchr::memchr;
1364    ///
1365    /// use xwrust::xwtm;
1366    /// use xwrust::xwmd::xwcq::*;
1367    ///
1368    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1369    ///
1370    /// pub fn xwrust_example_xwcq() {
1371    ///     CQ.init();
1372    ///     // ...省略...
1373    ///     let rc = CQ.pfq_to::<[u8; 64]>(xwtm::ft(xwtm::s(1)));
1374    ///     match rc {
1375    ///         Ok(d) => { // 获取数据成功
1376    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1377    ///             let totalslice = &d[0..64];
1378    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1379    ///             let msgu8slice = &d[0..nullpos];
1380    ///             let msg = str::from_utf8(msgu8slice);
1381    ///         },
1382    ///         Err(e) => { // 获取数据失败
1383    ///             break;
1384    ///         },
1385    ///     };
1386    /// }
1387    /// ```
1388    ///
1389    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1390    pub fn pfq_to<T>(&self, to: XwTm) -> Result<T, XwcqError>
1391    where
1392        T: Sized + Send
1393    {
1394        unsafe {
1395            let mut datasz: XwSz = mem::size_of::<T>();
1396            if datasz <= self.size() {
1397                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1398                if rc == 0 {
1399                    let mut data: T = mem::zeroed();
1400                    rc = xwcq_pfq_to(self.cq.get(),
1401                                     &mut data as *mut T as *mut u8, &mut datasz as _,
1402                                     to);
1403                    xwcq_put(self.cq.get());
1404                    if XWOK == rc {
1405                        Ok(data)
1406                    } else if  -EINTR == rc {
1407                        Err(XwcqError::Interrupt(rc))
1408                    } else if -ETIMEDOUT == rc {
1409                        Err(XwcqError::Timedout(rc))
1410                    } else if -ENOTTHDCTX == rc {
1411                        Err(XwcqError::NotThreadContext(rc))
1412                    } else if -EDISPMPT == rc {
1413                        Err(XwcqError::DisPmpt(rc))
1414                    } else if -EDISBH == rc {
1415                        Err(XwcqError::DisBh(rc))
1416                    } else if -EDISIRQ == rc {
1417                        Err(XwcqError::DisIrq(rc))
1418                    } else {
1419                        Err(XwcqError::Unknown(rc))
1420                    }
1421                } else {
1422                    Err(XwcqError::NotInit(rc))
1423                }
1424            } else {
1425                Err(XwcqError::DataSize(-ESIZE))
1426            }
1427        }
1428    }
1429
1430    /// 等待从循环队列 **头端** 拷贝数据(Peek at the Front of Queue),并且等待不可被中断
1431    ///
1432    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1433    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1434    /// + 若循环队列为空,线程会阻塞等待,且不可被中断。
1435    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1436    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1437    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1438    ///
1439    /// # 上下文
1440    ///
1441    /// + 线程
1442    ///
1443    /// # 错误码
1444    ///
1445    /// + [`XwcqError::Ok`] 没有错误
1446    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1447    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1448    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1449    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1450    /// + [`XwcqError::DisIrq`] 中断被关闭
1451    ///
1452    /// # 示例
1453    ///
1454    /// ```rust
1455    /// extern crate core;
1456    /// use core::str;
1457    /// use core::slice::memchr::memchr;
1458    ///
1459    /// use xwrust::xwmd::xwcq::*;
1460    ///
1461    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1462    ///
1463    /// pub fn xwrust_example_xwcq() {
1464    ///     CQ.init();
1465    ///     // ...省略...
1466    ///     let rc = CQ.pfq_unintr::<[u8; 64]>();
1467    ///     match rc {
1468    ///         Ok(d) => { // 获取数据成功
1469    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1470    ///             let totalslice = &d[0..64];
1471    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1472    ///             let msgu8slice = &d[0..nullpos];
1473    ///             let msg = str::from_utf8(msgu8slice);
1474    ///         },
1475    ///         Err(e) => { // 获取数据失败
1476    ///             break;
1477    ///         },
1478    ///     };
1479    /// }
1480    /// ```
1481    ///
1482    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1483    pub fn pfq_unintr<T>(&self) -> Result<T, XwcqError>
1484    where
1485        T: Sized + Send
1486    {
1487        unsafe {
1488            let mut datasz: XwSz = mem::size_of::<T>();
1489            if datasz <= self.size() {
1490                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1491                if rc == 0 {
1492                    let mut data: T = mem::zeroed();
1493                    rc = xwcq_pfq_unintr(self.cq.get(),
1494                                         &mut data as *mut T as *mut u8,
1495                                         &mut datasz as _);
1496                    xwcq_put(self.cq.get());
1497                    if XWOK == rc {
1498                        Ok(data)
1499                    } else if -ENOTTHDCTX == rc {
1500                        Err(XwcqError::NotThreadContext(rc))
1501                    } else if -EDISPMPT == rc {
1502                        Err(XwcqError::DisPmpt(rc))
1503                    } else if -EDISBH == rc {
1504                        Err(XwcqError::DisBh(rc))
1505                    } else if -EDISIRQ == rc {
1506                        Err(XwcqError::DisIrq(rc))
1507                    } else {
1508                        Err(XwcqError::Unknown(rc))
1509                    }
1510                } else {
1511                    Err(XwcqError::NotInit(rc))
1512                }
1513            } else {
1514                Err(XwcqError::DataSize(-ESIZE))
1515            }
1516        }
1517    }
1518
1519    /// 尝试从循环队列 **头端** 拷贝数据(Peek at the Front of Queue)
1520    ///
1521    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1522    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1523    /// + 若循环队列为空,立即返回 [`XwcqError::DataSize`] ,此方法不会阻塞。
1524    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1525    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1526    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1527    ///
1528    /// # 上下文
1529    ///
1530    /// + 任意
1531    ///
1532    /// # 错误码
1533    ///
1534    /// + [`XwcqError::Ok`] 没有错误
1535    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1536    /// + [`XwcqError::NoData`] 循环队列中没有数据
1537    ///
1538    /// # 示例
1539    ///
1540    /// ```rust
1541    /// extern crate core;
1542    /// use core::str;
1543    /// use core::slice::memchr::memchr;
1544    ///
1545    /// use xwrust::xwmd::xwcq::*;
1546    ///
1547    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1548    ///
1549    /// pub fn xwrust_example_xwcq() {
1550    ///     CQ.init();
1551    ///     // ...省略...
1552    ///     let rc = CQ.trypfq::<[u8; 64]>();
1553    ///     match rc {
1554    ///         Ok(d) => { // 获取数据成功
1555    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1556    ///             let totalslice = &d[0..64];
1557    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1558    ///             let msgu8slice = &d[0..nullpos];
1559    ///             let msg = str::from_utf8(msgu8slice);
1560    ///         },
1561    ///         Err(e) => { // 获取数据失败
1562    ///         },
1563    ///     };
1564    /// }
1565    /// ```
1566    ///
1567    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1568    pub fn trypfq<T>(&self) -> Result<T, XwcqError>
1569    where
1570        T: Sized + Send
1571    {
1572        unsafe {
1573            let mut datasz: XwSz = mem::size_of::<T>();
1574            if datasz <= self.size() {
1575                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1576                if rc == 0 {
1577                    let mut data: T = mem::zeroed();
1578                    rc = xwcq_trypfq(self.cq.get(),
1579                                     &mut data as *mut T as *mut u8, &mut datasz as _);
1580                    xwcq_put(self.cq.get());
1581                    if XWOK == rc {
1582                        Ok(data)
1583                    } else if -ENODATA == rc {
1584                        Err(XwcqError::NoData(rc))
1585                    } else {
1586                        Err(XwcqError::Unknown(rc))
1587                    }
1588                } else {
1589                    Err(XwcqError::NotInit(rc))
1590                }
1591            } else {
1592                Err(XwcqError::DataSize(-ESIZE))
1593            }
1594        }
1595    }
1596
1597    /// 等待从循环队列 **尾端** 拷贝数据(Peek at the Rear of Queue)
1598    ///
1599    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1600    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1601    /// + 若循环队列为空,线程会阻塞等待。
1602    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1603    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1604    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1605    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
1606    ///
1607    /// # 上下文
1608    ///
1609    /// + 线程
1610    ///
1611    /// # 错误码
1612    ///
1613    /// + [`XwcqError::Ok`] 没有错误
1614    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1615    /// + [`XwcqError::Interrupt`] 等待被中断
1616    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1617    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1618    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1619    /// + [`XwcqError::DisIrq`] 中断被关闭
1620    ///
1621    /// # 示例
1622    ///
1623    /// ```rust
1624    /// extern crate core;
1625    /// use core::str;
1626    /// use core::slice::memchr::memchr;
1627    ///
1628    /// use xwrust::xwmd::xwcq::*;
1629    ///
1630    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1631    ///
1632    /// pub fn xwrust_example_xwcq() {
1633    ///     CQ.init();
1634    ///     // ...省略...
1635    ///     let rc = CQ.prq::<[u8; 64]>();
1636    ///     match rc {
1637    ///         Ok(d) => { // 获取数据成功
1638    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1639    ///             let totalslice = &d[0..64];
1640    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1641    ///             let msgu8slice = &d[0..nullpos];
1642    ///             let msg = str::from_utf8(msgu8slice);
1643    ///         },
1644    ///         Err(e) => { // 获取数据失败
1645    ///             break;
1646    ///         },
1647    ///     };
1648    /// }
1649    /// ```
1650    ///
1651    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1652    pub fn prq<T>(&self) -> Result<T, XwcqError>
1653    where
1654        T: Sized + Send
1655    {
1656        unsafe {
1657            let mut datasz: XwSz = mem::size_of::<T>();
1658            if datasz <= self.size() {
1659                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1660                if rc == 0 {
1661                    let mut data: T = mem::zeroed();
1662                    rc = xwcq_prq(self.cq.get(),
1663                                  &mut data as *mut T as *mut u8, &mut datasz as _);
1664                    xwcq_put(self.cq.get());
1665                    if XWOK == rc {
1666                        Ok(data)
1667                    } else if  -EINTR == rc {
1668                        Err(XwcqError::Interrupt(rc))
1669                    } else if -ENOTTHDCTX == rc {
1670                        Err(XwcqError::NotThreadContext(rc))
1671                    } else if -EDISPMPT == rc {
1672                        Err(XwcqError::DisPmpt(rc))
1673                    } else if -EDISBH == rc {
1674                        Err(XwcqError::DisBh(rc))
1675                    } else if -EDISIRQ == rc {
1676                        Err(XwcqError::DisIrq(rc))
1677                    } else {
1678                        Err(XwcqError::Unknown(rc))
1679                    }
1680                } else {
1681                    Err(XwcqError::NotInit(rc))
1682                }
1683            } else {
1684                Err(XwcqError::DataSize(-ESIZE))
1685            }
1686        }
1687    }
1688
1689    /// 限时等待从循环队列 **尾端** 拷贝数据(Peek at the Rear of Queue)
1690    ///
1691    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1692    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1693    /// + 若循环队列为空,线程会阻塞等待,等待时会指定一个唤醒时间点。
1694    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1695    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1696    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1697    /// + 当线程阻塞等待被中断时,返回错误码 [`XwcqError::Interrupt`] 。
1698    /// + 当到达指定的唤醒时间点,线程被唤醒,返回错误码 [`XwcqError::Timedout`] 。
1699    ///
1700    /// # 参数说明
1701    ///
1702    /// + to: 期望唤醒的时间点
1703    ///
1704    /// # 上下文
1705    ///
1706    /// + 线程
1707    ///
1708    /// # 错误码
1709    ///
1710    /// + [`XwcqError::Ok`] 没有错误
1711    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1712    /// + [`XwcqError::Interrupt`] 等待被中断
1713    /// + [`XwcqError::Timedout`] 等待超时
1714    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1715    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1716    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1717    /// + [`XwcqError::DisIrq`] 中断被关闭
1718    ///
1719    /// # 示例
1720    ///
1721    /// ```rust
1722    /// extern crate core;
1723    /// use core::str;
1724    /// use core::slice::memchr::memchr;
1725    ///
1726    /// use xwrust::xwtm;
1727    /// use xwrust::xwmd::xwcq::*;
1728    ///
1729    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1730    ///
1731    /// pub fn xwrust_example_xwcq() {
1732    ///     CQ.init();
1733    ///     // ...省略...
1734    ///     let rc = CQ.prq_to::<[u8; 64]>(xwtm::ft(xwtm::s(1)));
1735    ///     match rc {
1736    ///         Ok(d) => { // 获取数据成功
1737    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1738    ///             let totalslice = &d[0..64];
1739    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1740    ///             let msgu8slice = &d[0..nullpos];
1741    ///             let msg = str::from_utf8(msgu8slice);
1742    ///         },
1743    ///         Err(e) => { // 获取数据失败
1744    ///             break;
1745    ///         },
1746    ///     };
1747    /// }
1748    /// ```
1749    ///
1750    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1751    pub fn prq_to<T>(&self, to: XwTm) -> Result<T, XwcqError>
1752    where
1753        T: Sized + Send
1754    {
1755        unsafe {
1756            let mut datasz: XwSz = mem::size_of::<T>();
1757            if datasz <= self.size() {
1758                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1759                if rc == 0 {
1760                    let mut data: T = mem::zeroed();
1761                    rc = xwcq_prq_to(self.cq.get(),
1762                                     &mut data as *mut T as *mut u8, &mut datasz as _,
1763                                     to);
1764                    xwcq_put(self.cq.get());
1765                    if XWOK == rc {
1766                        Ok(data)
1767                    } else if  -EINTR == rc {
1768                        Err(XwcqError::Interrupt(rc))
1769                    } else if -ETIMEDOUT == rc {
1770                        Err(XwcqError::Timedout(rc))
1771                    } else if -ENOTTHDCTX == rc {
1772                        Err(XwcqError::NotThreadContext(rc))
1773                    } else if -EDISPMPT == rc {
1774                        Err(XwcqError::DisPmpt(rc))
1775                    } else if -EDISBH == rc {
1776                        Err(XwcqError::DisBh(rc))
1777                    } else if -EDISIRQ == rc {
1778                        Err(XwcqError::DisIrq(rc))
1779                    } else {
1780                        Err(XwcqError::Unknown(rc))
1781                    }
1782                } else {
1783                    Err(XwcqError::NotInit(rc))
1784                }
1785            } else {
1786                Err(XwcqError::DataSize(-ESIZE))
1787            }
1788        }
1789    }
1790
1791    /// 等待从循环队列 **尾端** 拷贝数据(Peek at the Rear of Queue),并且等待不可被中断
1792    ///
1793    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1794    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1795    /// + 若循环队列为空,线程会阻塞等待,且不可被中断。
1796    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1797    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1798    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1799    ///
1800    /// # 上下文
1801    ///
1802    /// + 线程
1803    ///
1804    /// # 错误码
1805    ///
1806    /// + [`XwcqError::Ok`] 没有错误
1807    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1808    /// + [`XwcqError::NotThreadContext`] 不在线程上下文内
1809    /// + [`XwcqError::DisPmpt`] 抢占被关闭
1810    /// + [`XwcqError::DisBh`] 中断底半部被关闭
1811    /// + [`XwcqError::DisIrq`] 中断被关闭
1812    ///
1813    /// # 示例
1814    ///
1815    /// ```rust
1816    /// extern crate core;
1817    /// use core::str;
1818    /// use core::slice::memchr::memchr;
1819    ///
1820    /// use xwrust::xwmd::xwcq::*;
1821    ///
1822    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1823    ///
1824    /// pub fn xwrust_example_xwcq() {
1825    ///     CQ.init();
1826    ///     // ...省略...
1827    ///     let rc = CQ.prq_unintr::<[u8; 64]>();
1828    ///     match rc {
1829    ///         Ok(d) => { // 获取数据成功
1830    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1831    ///             let totalslice = &d[0..64];
1832    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1833    ///             let msgu8slice = &d[0..nullpos];
1834    ///             let msg = str::from_utf8(msgu8slice);
1835    ///         },
1836    ///         Err(e) => { // 获取数据失败
1837    ///             break;
1838    ///         },
1839    ///     };
1840    /// }
1841    /// ```
1842    ///
1843    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1844    pub fn prq_unintr<T>(&self) -> Result<T, XwcqError>
1845    where
1846        T: Sized + Send
1847    {
1848        unsafe {
1849            let mut datasz: XwSz = mem::size_of::<T>();
1850            if datasz <= self.size() {
1851                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1852                if rc == 0 {
1853                    let mut data: T = mem::zeroed();
1854                    rc = xwcq_prq_unintr(self.cq.get(),
1855                                         &mut data as *mut T as *mut u8,
1856                                         &mut datasz as _);
1857                    xwcq_put(self.cq.get());
1858                    if XWOK == rc {
1859                        Ok(data)
1860                    } else if -ENOTTHDCTX == rc {
1861                        Err(XwcqError::NotThreadContext(rc))
1862                    } else if -EDISPMPT == rc {
1863                        Err(XwcqError::DisPmpt(rc))
1864                    } else if -EDISBH == rc {
1865                        Err(XwcqError::DisBh(rc))
1866                    } else if -EDISIRQ == rc {
1867                        Err(XwcqError::DisIrq(rc))
1868                    } else {
1869                        Err(XwcqError::Unknown(rc))
1870                    }
1871                } else {
1872                    Err(XwcqError::NotInit(rc))
1873                }
1874            } else {
1875                Err(XwcqError::DataSize(-ESIZE))
1876            }
1877        }
1878    }
1879
1880    /// 尝试从循环队列 **尾端** 拷贝数据(Peek at the Rear of Queue)
1881    ///
1882    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1883    /// + 拷贝数据不会取走数据,也不会释放数据槽,数据可被重复拷贝,也可继续被接收。
1884    /// + 若循环队列为空,立即返回 [`XwcqError::DataSize`] ,此方法不会阻塞。
1885    /// + 接收时,数据类型是泛型 `T` ,`T` 必须是 [`Sized`] 的,数据是被逐字节地从循环队列的数据槽中拷贝到出来的。
1886    /// + 循环队列不会对接收时的 `T` 与 发送时的 `T` 进行检查,因此用户必须确保两个类型是一样的,或能安全地进行转换。
1887    /// + 当 `T` 大小大于循环队列的数据槽大小 `S` ,接收会失败,并返回错误码 [`XwcqError::DataSize`] 。
1888    ///
1889    /// # 上下文
1890    ///
1891    /// + 任意
1892    ///
1893    /// # 错误码
1894    ///
1895    /// + [`XwcqError::Ok`] 没有错误
1896    /// + [`XwcqError::NotInit`] 循环队列没有初始化
1897    /// + [`XwcqError::NoData`] 循环队列中没有数据
1898    ///
1899    /// # 示例
1900    ///
1901    /// ```rust
1902    /// extern crate core;
1903    /// use core::str;
1904    /// use core::slice::memchr::memchr;
1905    ///
1906    /// use xwrust::xwmd::xwcq::*;
1907    ///
1908    /// static CQ: Xwcq<64, 16> = Xwcq::new();
1909    ///
1910    /// pub fn xwrust_example_xwcq() {
1911    ///     CQ.init();
1912    ///     // ...省略...
1913    ///     let rc = CQ.tryprq::<[u8; 64]>();
1914    ///     match rc {
1915    ///         Ok(d) => { // 获取数据成功
1916    ///             // 从 `[u8; 64]` 数组中构建切片 `&str`
1917    ///             let totalslice = &d[0..64];
1918    ///             let nullpos = memchr(0, totalslice).unwrap_or(64);
1919    ///             let msgu8slice = &d[0..nullpos];
1920    ///             let msg = str::from_utf8(msgu8slice);
1921    ///         },
1922    ///         Err(e) => { // 获取数据失败
1923    ///         },
1924    ///     };
1925    /// }
1926    /// ```
1927    ///
1928    /// [`Sized`]: <https://doc.rust-lang.org/std/marker/trait.Sized.html>
1929    pub fn tryprq<T>(&self) -> Result<T, XwcqError>
1930    where
1931        T: Sized + Send
1932    {
1933        unsafe {
1934            let mut datasz: XwSz = mem::size_of::<T>();
1935            if datasz <= self.size() {
1936                let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1937                if rc == 0 {
1938                    let mut data: T = mem::zeroed();
1939                    rc = xwcq_tryprq(self.cq.get(),
1940                                     &mut data as *mut T as *mut u8, &mut datasz as _);
1941                    xwcq_put(self.cq.get());
1942                    if XWOK == rc {
1943                        Ok(data)
1944                    } else if -ENODATA == rc {
1945                        Err(XwcqError::NoData(rc))
1946                    } else {
1947                        Err(XwcqError::Unknown(rc))
1948                    }
1949                } else {
1950                    Err(XwcqError::NotInit(rc))
1951                }
1952            } else {
1953                Err(XwcqError::DataSize(-ESIZE))
1954            }
1955        }
1956    }
1957
1958    /// 清空循环队列
1959    ///
1960    /// + 当循环队列未初始化,返回错误码 [`XwcqError::NotInit`] 。
1961    ///
1962    /// # 上下文
1963    ///
1964    /// + 任意
1965    pub fn flush(&self) -> XwcqError {
1966        unsafe {
1967            let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
1968            if rc == 0 {
1969                rc = xwcq_flush(self.cq.get());
1970                xwcq_put(self.cq.get());
1971                if XWOK == rc {
1972                    XwcqError::Ok(rc)
1973                } else {
1974                    XwcqError::Unknown(rc)
1975                }
1976            } else {
1977                XwcqError::NotInit(rc)
1978            }
1979        }
1980    }
1981
1982    /// 获取循环队列的容量
1983    ///
1984    /// 循环队列的容量也即是数据槽的数量,是在创建循环队列时,指明的类型常数 `N` 。
1985    ///
1986    /// # 上下文
1987    ///
1988    /// + 任意
1989    pub const fn capacity(&self) -> XwSz {
1990        N
1991    }
1992
1993    /// 获取循环队列的单个数据槽的大小
1994    ///
1995    /// 循环队列的单个数据槽的大小是在创建循环队列时,指明的类型常数 `S` 。
1996    /// 若 `S` 不满足内存对齐的要求,会自动向上调整。
1997    ///
1998    /// # 上下文
1999    ///
2000    /// + 任意
2001    pub const fn size(&self) -> XwSz {
2002        (S + XWCQ_MM_ALIGN - 1) & (!XWCQ_MM_MSK)
2003    }
2004
2005    /// 获取循环队列中有效数据槽的数量
2006    ///
2007    /// 有效数据槽是指包含了可被接收数据的数据槽。
2008    ///
2009    /// # 上下文
2010    ///
2011    /// + 任意
2012    pub fn availability(&self) -> Result<XwSz, XwcqError> {
2013        unsafe {
2014            let mut rc = xwrustffi_xwcq_acquire(self.cq.get(), *self.tik.get());
2015            if rc == 0 {
2016                let mut avb: XwSz = 0;
2017                rc = xwcq_get_availability(self.cq.get(), &mut avb);
2018                xwcq_put(self.cq.get());
2019                if XWOK == rc {
2020                    Ok(avb)
2021                } else {
2022                    Err(XwcqError::Unknown(rc))
2023                }
2024            } else {
2025                Err(XwcqError::NotInit(rc))
2026            }
2027        }
2028    }
2029}