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