author | unC0Rr |
Thu, 25 Jul 2019 15:18:00 +0200 | |
changeset 15265 | 07e909ba4203 |
permissions | -rw-r--r-- |
15265
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 |
} |