1use std::{cmp::Ordering, marker::PhantomData, ops::Add, time::Duration};
2
3use prosa_utils::{
4 hash::{BuildIntHasher, IntHashMap},
5 msg::tvf::Tvf,
6};
7use tokio::time::{Instant, Sleep, sleep_until};
8
9use crate::core::msg::Msg;
10
11#[derive(Debug)]
13struct PendingTimer<T>
14where
15 T: Copy,
16{
17 timer_id: T,
18 timeout: Instant,
19}
20
21impl<T> PendingTimer<T>
22where
23 T: Copy,
24{
25 pub(crate) fn new(timer_id: T, timeout_duration: Duration) -> PendingTimer<T> {
27 PendingTimer {
28 timer_id,
29 timeout: Instant::now().add(timeout_duration),
30 }
31 }
32
33 pub(crate) fn new_at(timer_id: T, timeout: Instant) -> PendingTimer<T> {
35 PendingTimer { timer_id, timeout }
36 }
37
38 pub(crate) fn get_timer_id(&self) -> T {
40 self.timer_id
41 }
42
43 pub(crate) fn is_expired(&self) -> bool {
45 self.timeout <= Instant::now()
46 }
47
48 pub(crate) fn sleep(&self) -> Sleep {
50 sleep_until(self.timeout)
51 }
52}
53
54impl<T> Ord for PendingTimer<T>
55where
56 T: Copy,
57{
58 fn cmp(&self, other: &Self) -> Ordering {
59 self.timeout.cmp(&other.timeout)
60 }
61}
62
63impl<T> PartialOrd for PendingTimer<T>
64where
65 T: Copy,
66{
67 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68 Some(self.cmp(other))
69 }
70}
71
72impl<T> PartialEq for PendingTimer<T>
73where
74 T: Copy,
75{
76 fn eq(&self, other: &Self) -> bool {
77 self.timeout == other.timeout
78 }
79}
80
81impl<T> Eq for PendingTimer<T> where T: Copy {}
82
83#[derive(Debug, Default)]
101pub struct Timers<T>
102where
103 T: Copy,
104{
105 timers: Vec<PendingTimer<T>>,
106}
107
108impl<T> Timers<T>
109where
110 T: Copy,
111{
112 pub fn len(&self) -> usize {
114 self.timers.len()
115 }
116
117 pub fn capacity(&self) -> usize {
119 self.timers.capacity()
120 }
121
122 pub fn is_empty(&self) -> bool {
124 self.timers.is_empty()
125 }
126
127 pub fn with_capacity(capacity: usize) -> Self {
129 Timers {
130 timers: Vec::with_capacity(capacity),
131 }
132 }
133
134 fn push_timer(&mut self, timer: PendingTimer<T>) {
136 let mut timer_iter = self.timers.iter();
137 let index = loop {
138 if let Some(val) = timer_iter.next() {
139 if timer > *val {
140 break self.timers.len() - (timer_iter.count() + 1);
141 }
142 } else {
143 break self.timers.len();
144 }
145 };
146
147 self.timers.insert(index, timer);
148 }
149
150 pub fn push(&mut self, timer_id: T, timeout_duration: Duration) {
152 self.push_timer(PendingTimer::new(timer_id, timeout_duration));
153 }
154
155 pub fn push_at(&mut self, timer_id: T, timeout: Instant) {
157 self.push_timer(PendingTimer::new_at(timer_id, timeout));
158 }
159
160 pub async fn pull(&mut self) -> Option<T> {
177 if let Some(timer) = self.timers.last() {
178 if !timer.is_expired() {
179 timer.sleep().await;
180 }
181
182 self.timers.pop().map(|t| t.get_timer_id())
183 } else {
184 None
185 }
186 }
187
188 pub fn retain<F>(&mut self, mut f: F)
206 where
207 F: FnMut(T) -> bool,
208 {
209 self.timers.retain(|t| f(t.timer_id));
210 }
211
212 fn pop(&mut self) -> Option<PendingTimer<T>> {
214 self.timers.pop()
215 }
216
217 fn last(&self) -> Option<&PendingTimer<T>> {
219 self.timers.last()
220 }
221}
222
223#[derive(Debug)]
257pub struct PendingMsgs<T, M>
258where
259 T: Msg<M>,
260 M: Sized + Clone + Tvf,
261{
262 pending_messages: IntHashMap<u64, T>,
263 timers: Timers<u64>,
264 phantom: PhantomData<M>,
265}
266
267impl<T, M> PendingMsgs<T, M>
268where
269 T: Msg<M>,
270 M: Sized + Clone + Tvf,
271{
272 pub fn len(&self) -> usize {
274 self.pending_messages.len()
275 }
276
277 pub fn capacity(&self) -> usize {
279 self.pending_messages.capacity()
280 }
281
282 pub fn is_empty(&self) -> bool {
284 self.pending_messages.is_empty()
285 }
286
287 pub fn with_capacity(capacity: usize) -> Self
289 where
290 T: Msg<M>,
291 M: Sized + Clone + Tvf,
292 {
293 PendingMsgs {
294 pending_messages: IntHashMap::with_capacity_and_hasher(
295 capacity,
296 BuildIntHasher::default(),
297 ),
298 timers: Timers::with_capacity(capacity),
299 phantom: PhantomData,
300 }
301 }
302
303 pub fn push(&mut self, msg: T, timeout: Duration) {
305 self.push_with_id(msg.get_id(), msg, timeout);
306 }
307
308 pub fn push_with_id(&mut self, id: u64, msg: T, timeout: Duration) {
310 self.timers.push(id, timeout);
311 self.pending_messages.insert(id, msg);
312 }
313
314 pub fn pull_msg(&mut self, msg_id: u64) -> Option<T> {
316 if let Some(msg) = self.pending_messages.remove(&msg_id) {
317 return Some(msg);
318 }
319
320 None
321 }
322
323 pub async fn pull(&mut self) -> Option<T> {
346 while let Some(timer) = self.timers.last() {
347 if self.pending_messages.contains_key(&timer.get_timer_id()) {
348 if !timer.is_expired() {
349 timer.sleep().await;
350 }
351
352 let time = self.timers.pop()?;
353 return self.pull_msg(time.get_timer_id());
354 } else {
355 self.timers.pop();
356 }
357 }
358
359 None
360 }
361}
362
363impl<T, M> Default for PendingMsgs<T, M>
364where
365 T: Msg<M>,
366 M: Sized + Clone + Tvf,
367{
368 fn default() -> Self {
369 PendingMsgs::<T, M> {
370 pending_messages: Default::default(),
371 timers: Default::default(),
372 phantom: PhantomData,
373 }
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 extern crate self as prosa;
380
381 use std::time::Duration;
382
383 use prosa_macros::{proc, settings};
384 use prosa_utils::msg::{simple_string_tvf::SimpleStringTvf, tvf::Tvf};
385 use serde::Serialize;
386 use tokio::time::timeout;
387
388 use crate::core::{
389 error::BusError,
390 main::{MainProc, MainRunnable},
391 msg::{InternalMsg, Msg, RequestMsg},
392 proc::{ProcBusParam, ProcConfig},
393 };
394
395 use super::{PendingMsgs, Timers};
396
397 #[proc]
398 pub(crate) struct TestProc {}
399
400 #[proc]
401 impl TestProc<SimpleStringTvf> {
402 async fn timers_run(&mut self) -> Result<(), BusError> {
403 self.proc.add_proc().await?;
405 self.proc
406 .add_service_proc(vec![String::from("TEST")])
407 .await?;
408
409 let mut pending_timer: Timers<u64> = Default::default();
410 loop {
411 tokio::select! {
412 Some(msg) = self.internal_rx_queue.recv() => {
413 match msg {
414 InternalMsg::Request(_) => {
415 assert_eq!(0, pending_timer.len());
416 pending_timer.push(1, Duration::from_millis(100));
417 assert_eq!(1, pending_timer.len());
418 },
419 InternalMsg::Service(table) => {
420 if let Some(service) = table.get_proc_service("TEST") {
421 service.proc_queue.send(InternalMsg::Request(RequestMsg::new(String::from("TEST"), Default::default(), self.proc.get_service_queue().clone()))).await.expect("Internal msg should be send");
422 }
423 },
424 _ => return Err(BusError::ProcComm(self.get_proc_id(), 0, String::from("Wrong message"))),
425 }
426 },
427 Some(timer_id) = pending_timer.pull(), if !pending_timer.is_empty() => {
428 assert_eq!(0, pending_timer.len());
429 assert_eq!(1, timer_id);
430 self.proc.remove_proc(None).await?;
431 return Ok(())
432 },
433 }
434 }
435 }
436
437 async fn pending_msgs_run(&mut self) -> Result<(), BusError> {
438 self.proc.add_proc().await?;
440 self.proc
441 .add_service_proc(vec![String::from("TEST")])
442 .await?;
443
444 let mut pending_msg: PendingMsgs<RequestMsg<SimpleStringTvf>, SimpleStringTvf> =
445 Default::default();
446 loop {
447 tokio::select! {
448 Some(msg) = self.internal_rx_queue.recv() => {
449 match msg {
450 InternalMsg::Request(msg) => {
451 assert_eq!(0, pending_msg.len());
452 pending_msg.push(msg, Duration::from_millis(100));
453 assert_eq!(1, pending_msg.len());
454 },
455 InternalMsg::Service(table) => {
456 if let Some(service) = table.get_proc_service("TEST") {
457 let mut msg: SimpleStringTvf = Default::default();
458 msg.put_string(1, "good");
459 service.proc_queue.send(InternalMsg::Request(RequestMsg::new(String::from("TEST"), msg, self.proc.get_service_queue().clone()))).await.expect("Internal msg should be send");
460 }
461 },
462 _ => return Err(BusError::ProcComm(self.get_proc_id(), 0, String::from("Wrong message"))),
463 }
464 },
465 Some(msg) = pending_msg.pull(), if !pending_msg.is_empty() => {
466 assert_eq!(0, pending_msg.len());
467 assert_eq!(String::from("good"), msg.get_data()?.get_string(1)?.into_owned());
468 self.proc.remove_proc(None).await?;
469 return Ok(())
470 },
471 }
472 }
473 }
474
475 pub(crate) async fn timers_timeout_run(&mut self) -> Result<(), BusError> {
476 if timeout(Duration::from_millis(200), self.timers_run())
477 .await
478 .is_err()
479 {
480 Err(BusError::InternalQueue(String::from(
481 "Timer is not working",
482 )))
483 } else {
484 Ok(())
485 }
486 }
487
488 pub(crate) async fn pending_msgs_timeout_run(&mut self) -> Result<(), BusError> {
489 if timeout(Duration::from_millis(200), self.pending_msgs_run())
490 .await
491 .is_err()
492 {
493 Err(BusError::InternalQueue(String::from(
494 "pending msgs is not working",
495 )))
496 } else {
497 Ok(())
498 }
499 }
500 }
501
502 #[test]
503 fn test_with_capacity() {
504 let capacity = 10;
505 let pending_msg: PendingMsgs<RequestMsg<SimpleStringTvf>, SimpleStringTvf> =
506 PendingMsgs::with_capacity(capacity);
507 assert_eq!(pending_msg.len(), 0);
508 assert!(pending_msg.is_empty());
509 assert!(pending_msg.capacity() >= capacity);
510
511 let pending_timer: Timers<u64> = Timers::with_capacity(capacity);
512 assert_eq!(pending_timer.len(), 0);
513 assert!(pending_timer.is_empty());
514 assert!(pending_timer.capacity() >= capacity);
515 }
516
517 #[tokio::test]
518 async fn test_pending() {
519 #[settings]
521 #[derive(Default, Debug, Serialize)]
522 struct DummySettings {}
523
524 let (bus, main) = MainProc::<SimpleStringTvf>::create(&DummySettings::default(), Some(2));
526
527 let main_task = tokio::spawn(main.run());
529
530 assert_eq!(
532 Ok(()),
533 TestProc::<SimpleStringTvf>::create_raw(1, "test1".to_string(), bus.clone())
534 .timers_timeout_run()
535 .await
536 );
537
538 assert_eq!(
539 Ok(()),
540 TestProc::<SimpleStringTvf>::create_raw(2, "test2".to_string(), bus.clone())
541 .pending_msgs_timeout_run()
542 .await
543 );
544
545 bus.stop("ProSA unit test end".into())
546 .await
547 .expect("ProSA should stop");
548 main_task.await.expect("Main task should end correctly");
549 }
550}