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}