11use crate :: host:: host:: Host ;
2+ use crate :: network:: packet:: Packet ;
23use crate :: utility:: { Magic , ObjectCounter } ;
34use shadow_shim_helper_rs:: emulated_time:: EmulatedTime ;
45use shadow_shim_helper_rs:: HostId ;
@@ -8,51 +9,55 @@ use super::task::TaskRef;
89#[ derive( Debug ) ]
910pub struct Event {
1011 magic : Magic < Self > ,
11- task : TaskRef ,
1212 time : EmulatedTime ,
13- src_host_id : HostId ,
14- dst_host_id : HostId ,
15- src_host_event_id : u64 ,
13+ data : EventData ,
1614 _counter : ObjectCounter ,
1715}
1816
1917impl Event {
20- pub fn new ( task : TaskRef , time : EmulatedTime , src_host : & Host , dst_host_id : HostId ) -> Self {
18+ /// A new packet event, which is an event for packets arriving from the Internet. Packet events
19+ /// do not include packets on localhost.
20+ pub fn new_packet ( packet : Packet , time : EmulatedTime , src_host : & Host ) -> Self {
2121 Self {
2222 magic : Magic :: new ( ) ,
23- task,
2423 time,
25- src_host_id : src_host. id ( ) ,
26- dst_host_id,
27- src_host_event_id : src_host. get_new_event_id ( ) ,
24+ data : EventData :: Packet ( PacketEventData {
25+ packet,
26+ src_host_id : src_host. id ( ) ,
27+ src_host_event_id : src_host. get_new_event_id ( ) ,
28+ } ) ,
2829 _counter : ObjectCounter :: new ( "Event" ) ,
2930 }
3031 }
3132
32- pub fn execute ( self , host : & Host ) {
33- self . magic . debug_check ( ) ;
34-
35- // make sure we're executing on the correct host
36- assert_eq ! ( self . host_id( ) , host. id( ) ) ;
37-
38- host. continue_execution_timer ( ) ;
39- self . task . execute ( host) ;
40- host. stop_execution_timer ( ) ;
33+ /// A new local event, which is an event that was generated locally by the host itself (timers,
34+ /// localhost packets, etc).
35+ pub fn new_local ( task : TaskRef , time : EmulatedTime , host : & Host ) -> Self {
36+ Self {
37+ magic : Magic :: new ( ) ,
38+ time,
39+ data : EventData :: Local ( LocalEventData {
40+ task,
41+ event_id : host. get_new_event_id ( ) ,
42+ } ) ,
43+ _counter : ObjectCounter :: new ( "Event" ) ,
44+ }
4145 }
4246
4347 pub fn time ( & self ) -> EmulatedTime {
4448 self . magic . debug_check ( ) ;
4549 self . time
4650 }
4751
48- pub fn host_id ( & self ) -> HostId {
52+ pub fn set_time ( & mut self , time : EmulatedTime ) {
4953 self . magic . debug_check ( ) ;
50- self . dst_host_id
54+ self . time = time ;
5155 }
5256
53- pub fn set_time ( & mut self , time : EmulatedTime ) {
57+ /// The event data.
58+ pub fn data ( self ) -> EventData {
5459 self . magic . debug_check ( ) ;
55- self . time = time ;
60+ self . data
5661 }
5762}
5863
@@ -61,30 +66,107 @@ impl PartialEq for Event {
6166 self . magic . debug_check ( ) ;
6267 other. magic . debug_check ( ) ;
6368
69+ fn check_impl_eq ( _: impl Eq ) { }
70+
71+ // below we impl Eq for Event, so we should make sure that all of our comparisons below are
72+ // also Eq
73+ check_impl_eq ( self . time ) ;
74+ check_impl_eq ( & self . data ) ;
75+
6476 // check every field except '_counter'
65- self . task == other. task
66- && self . time == other. time
67- && self . src_host_id == other. src_host_id
68- && self . dst_host_id == other. dst_host_id
69- && self . src_host_event_id == other. src_host_event_id
77+ self . time == other. time && self . data == other. data
7078 }
7179}
7280
81+ // we checked above that Event's `PartialEq` impl is also `Eq`
7382impl Eq for Event { }
7483
7584impl PartialOrd for Event {
7685 fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
7786 self . magic . debug_check ( ) ;
7887 other. magic . debug_check ( ) ;
7988
80- // sort by event time first, then use other fields we're able to compare
89+ // sort by event time, then by the event data
90+ let cmp = self . time . cmp ( & other. time ) ;
91+
92+ if cmp. is_ne ( ) {
93+ Some ( cmp)
94+ } else {
95+ // event times were equal
96+ self . data . partial_cmp ( & other. data )
97+ }
98+ }
99+ }
100+
101+ /// Data for an event. Different event types will contain different data.
102+ #[ derive( Debug , PartialEq , Eq , PartialOrd ) ]
103+ pub enum EventData {
104+ // IMPORTANT: The order of these enum variants is important and deliberate. The `PartialOrd`
105+ // derive affects the order of events in the event queue, and therefore which events are
106+ // processed before others (packet events will be processed before local events), and changing
107+ // this could significantly affect the simulation, possibly leading to incorrect behaviour.
108+ Packet ( PacketEventData ) ,
109+ Local ( LocalEventData ) ,
110+ }
111+
112+ #[ derive( Debug , PartialEq , Eq ) ]
113+ pub struct PacketEventData {
114+ packet : Packet ,
115+ src_host_id : HostId ,
116+ src_host_event_id : u64 ,
117+ }
118+
119+ #[ derive( Debug , PartialEq , Eq ) ]
120+ pub struct LocalEventData {
121+ task : TaskRef ,
122+ event_id : u64 ,
123+ }
124+
125+ impl PacketEventData {
126+ /// Get the packet contained within this event.
127+ pub fn packet ( self ) -> Packet {
128+ self . packet
129+ }
130+ }
131+
132+ impl PartialOrd for PacketEventData {
133+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
134+ // sort by src host ID, then by event ID
81135 let cmp = self
82- . time
83- . cmp ( & other. time )
84- . then_with ( || self . dst_host_id . cmp ( & other. dst_host_id ) )
85- . then_with ( || self . src_host_id . cmp ( & other. src_host_id ) )
136+ . src_host_id
137+ . cmp ( & other. src_host_id )
86138 . then_with ( || self . src_host_event_id . cmp ( & other. src_host_event_id ) ) ;
87139
140+ // if the above fields were all equal (this should ideally not occur in practice since it
141+ // leads to non-determinism, but we handle it anyways)
142+ if cmp == std:: cmp:: Ordering :: Equal {
143+ if self . packet != other. packet {
144+ // packets are not equal, so the events must not be equal
145+ assert_ne ! ( self , other) ;
146+ // we have nothing left to order them by
147+ return None ;
148+ }
149+
150+ // packets are equal, so the events must be equal
151+ assert_eq ! ( self , other) ;
152+ }
153+
154+ Some ( cmp)
155+ }
156+ }
157+
158+ impl LocalEventData {
159+ /// Get the task contained within this event.
160+ pub fn task ( self ) -> TaskRef {
161+ self . task
162+ }
163+ }
164+
165+ impl PartialOrd for LocalEventData {
166+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
167+ // they are local events and should be on the same host, so we can just sort by event ID
168+ let cmp = self . event_id . cmp ( & other. event_id ) ;
169+
88170 // if the above fields were all equal (this should ideally not occur in practice since it
89171 // leads to non-determinism, but we handle it anyways)
90172 if cmp == std:: cmp:: Ordering :: Equal {
0 commit comments