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