rust/lib-hedgewars-engine/src/ipc/queue.rs
branchui-scaling
changeset 15663 d92eeb468dad
parent 15283 c4fd2813b127
parent 15471 9a76589e294e
child 15664 0b99e220568a
equal deleted inserted replaced
15283:c4fd2813b127 15663:d92eeb468dad
     1 use hedgewars_engine_messages::{
       
     2     messages::EngineMessage::*, messages::SyncedEngineMessage::*,
       
     3     messages::UnsyncedEngineMessage::*, messages::*,
       
     4 };
       
     5 use queues::*;
       
     6 
       
     7 #[derive(PartialEq)]
       
     8 pub enum QueueChatStrategy {
       
     9     NetworkGame,
       
    10     LocalGame,
       
    11 }
       
    12 
       
    13 pub struct MessagesQueue {
       
    14     strategy: QueueChatStrategy,
       
    15     hi_ticks: u32,
       
    16     unordered: Queue<EngineMessage>,
       
    17     ordered: Queue<EngineMessage>,
       
    18 }
       
    19 
       
    20 impl MessagesQueue {
       
    21     pub fn new(strategy: QueueChatStrategy) -> Self {
       
    22         MessagesQueue {
       
    23             strategy,
       
    24             hi_ticks: 0,
       
    25             unordered: queue![],
       
    26             ordered: queue![],
       
    27         }
       
    28     }
       
    29 
       
    30     fn is_unordered(&self, message: &EngineMessage) -> bool {
       
    31         match message {
       
    32             Unordered(_) => true,
       
    33             Unsynced(HogSay(_)) | Unsynced(ChatMessage(_)) | Unsynced(TeamMessage(_)) => {
       
    34                 self.strategy == QueueChatStrategy::NetworkGame
       
    35             }
       
    36             _ => false,
       
    37         }
       
    38     }
       
    39 
       
    40     pub fn push(&mut self, engine_message: EngineMessage) {
       
    41         if self.is_unordered(&engine_message) {
       
    42             self.unordered.add(engine_message).unwrap();
       
    43         } else if let Synced(TimeWrap, timestamp) = engine_message {
       
    44             self.ordered
       
    45                 .add(Synced(TimeWrap, timestamp + self.hi_ticks))
       
    46                 .unwrap();
       
    47             self.hi_ticks += 65536;
       
    48         } else if let Synced(message, timestamp) = engine_message {
       
    49             self.ordered
       
    50                 .add(Synced(message, timestamp + self.hi_ticks))
       
    51                 .unwrap();
       
    52         } else {
       
    53             self.ordered.add(engine_message).unwrap();
       
    54         }
       
    55     }
       
    56 
       
    57     pub fn pop(&mut self, timestamp: u32) -> Option<EngineMessage> {
       
    58         if let Ok(message) = self.unordered.remove() {
       
    59             Some(message)
       
    60         } else if let Ok(Synced(_, message_timestamp)) = self.ordered.peek() {
       
    61             if message_timestamp == timestamp {
       
    62                 self.ordered.remove().ok()
       
    63             } else {
       
    64                 None
       
    65             }
       
    66         } else {
       
    67             self.ordered.remove().ok()
       
    68         }
       
    69     }
       
    70 
       
    71     pub fn iter(&mut self, timestamp: u32) -> MessagesQueueIterator {
       
    72         MessagesQueueIterator {
       
    73             timestamp,
       
    74             queue: self,
       
    75         }
       
    76     }
       
    77 }
       
    78 
       
    79 pub struct MessagesQueueIterator<'a> {
       
    80     timestamp: u32,
       
    81     queue: &'a mut MessagesQueue,
       
    82 }
       
    83 
       
    84 impl<'a> Iterator for MessagesQueueIterator<'a> {
       
    85     type Item = EngineMessage;
       
    86 
       
    87     fn next(&mut self) -> Option<EngineMessage> {
       
    88         self.queue.pop(self.timestamp)
       
    89     }
       
    90 }
       
    91 
       
    92 #[test]
       
    93 fn queue_order() {
       
    94     use hedgewars_engine_messages::messages::UnorderedEngineMessage::*;
       
    95 
       
    96     let mut queue = MessagesQueue::new(QueueChatStrategy::LocalGame);
       
    97 
       
    98     queue.push(Synced(Skip, 1));
       
    99     queue.push(Unsynced(ChatMessage("hi".to_string())));
       
   100     queue.push(Synced(TimeWrap, 65535));
       
   101     queue.push(Unordered(Ping));
       
   102     queue.push(Synced(Skip, 2));
       
   103 
       
   104     let zero_tick: Vec<EngineMessage> = queue.iter(0).collect();
       
   105     assert_eq!(zero_tick, vec![Unordered(Ping)]);
       
   106     assert_eq!(queue.pop(1), Some(Synced(Skip, 1)));
       
   107     assert_eq!(queue.pop(1), Some(Unsynced(ChatMessage("hi".to_string()))));
       
   108     assert_eq!(queue.pop(1), None);
       
   109     assert_eq!(queue.pop(2), None);
       
   110     assert_eq!(queue.pop(65535), Some(Synced(TimeWrap, 65535)));
       
   111     assert_eq!(queue.pop(65535), None);
       
   112     assert_eq!(queue.pop(65538), Some(Synced(Skip, 65538)));
       
   113     assert_eq!(queue.pop(65538), None);
       
   114     assert_eq!(queue.pop(65539), None);
       
   115 }