1
- use std:: { io, ops :: ControlFlow , os:: fd:: AsRawFd } ;
1
+ use std:: { io, os:: fd:: AsRawFd } ;
2
2
3
3
use crate :: log:: dev_error;
4
4
use crate :: system:: {
@@ -9,8 +9,14 @@ use crate::system::{
9
9
use signal_hook:: consts:: * ;
10
10
11
11
pub ( super ) trait EventClosure : Sized {
12
- /// Reason why the event loop should break. This is the return type of [`EventDispatcher::event_loop`].
12
+ /// Reason why the event loop should break.
13
+ ///
14
+ /// See [`EventDispatcher::set_break`] for more information.
13
15
type Break ;
16
+ /// Reason why the event loop should exit.
17
+ ///
18
+ /// See [`EventDispatcher::set_exit`] for more information.
19
+ type Exit ;
14
20
/// Operation that the closure must do when a signal arrives.
15
21
fn on_signal ( & mut self , info : SignalInfo , dispatcher : & mut EventDispatcher < Self > ) ;
16
22
}
@@ -38,7 +44,7 @@ macro_rules! define_signals {
38
44
} ) ?, ) * ] ,
39
45
poll_set: PollSet :: new( ) ,
40
46
callbacks: Vec :: with_capacity( SIGNALS . len( ) ) ,
41
- status: ControlFlow :: Continue ( ( ) ) ,
47
+ status: Status :: Continue ,
42
48
} ;
43
49
44
50
$(
@@ -73,6 +79,53 @@ define_signals! {
73
79
SIGWINCH = 11 ,
74
80
}
75
81
82
+ enum Status < T : EventClosure > {
83
+ Continue ,
84
+ Stop ( StopReason < T > ) ,
85
+ }
86
+
87
+ impl < T : EventClosure > Status < T > {
88
+ fn is_break ( & self ) -> bool {
89
+ matches ! ( self , Self :: Stop ( StopReason :: Break ( _) ) )
90
+ }
91
+
92
+ fn take_stop ( & mut self ) -> Option < StopReason < T > > {
93
+ // If the status ends up to be `Continue`, we are replacing it by another `Continue`.
94
+ let status = std:: mem:: replace ( self , Self :: Continue ) ;
95
+ match status {
96
+ Status :: Continue => None ,
97
+ Status :: Stop ( reason) => Some ( reason) ,
98
+ }
99
+ }
100
+
101
+ fn take_break ( & mut self ) -> Option < T :: Break > {
102
+ match self . take_stop ( ) ? {
103
+ StopReason :: Break ( break_reason) => Some ( break_reason) ,
104
+ reason @ StopReason :: Exit ( _) => {
105
+ // Replace back the status because it was not a `Break`.
106
+ * self = Self :: Stop ( reason) ;
107
+ None
108
+ }
109
+ }
110
+ }
111
+
112
+ fn take_exit ( & mut self ) -> Option < T :: Exit > {
113
+ match self . take_stop ( ) ? {
114
+ reason @ StopReason :: Break ( _) => {
115
+ // Replace back the status because it was not an `Exit`.
116
+ * self = Self :: Stop ( reason) ;
117
+ None
118
+ }
119
+ StopReason :: Exit ( exit_reason) => Some ( exit_reason) ,
120
+ }
121
+ }
122
+ }
123
+
124
+ pub ( super ) enum StopReason < T : EventClosure > {
125
+ Break ( T :: Break ) ,
126
+ Exit ( T :: Exit ) ,
127
+ }
128
+
76
129
#[ derive( PartialEq , Eq , Hash , Clone ) ]
77
130
struct EventId ( usize ) ;
78
131
@@ -83,7 +136,7 @@ pub(super) struct EventDispatcher<T: EventClosure> {
83
136
signal_handlers : [ SignalHandler ; SIGNALS . len ( ) ] ,
84
137
poll_set : PollSet < EventId > ,
85
138
callbacks : Vec < Callback < T > > ,
86
- status : ControlFlow < T :: Break > ,
139
+ status : Status < T > ,
87
140
}
88
141
89
142
impl < T : EventClosure > EventDispatcher < T > {
@@ -107,7 +160,13 @@ impl<T: EventClosure> EventDispatcher<T> {
107
160
///
108
161
/// This means that the event loop will stop even if other events are ready.
109
162
pub ( super ) fn set_break ( & mut self , reason : T :: Break ) {
110
- self . status = ControlFlow :: Break ( reason) ;
163
+ self . status = Status :: Stop ( StopReason :: Break ( reason) ) ;
164
+ }
165
+
166
+ /// Stop the event loop when the callbacks for the events that are ready by now have been
167
+ /// dispatched and set a reason for it.
168
+ pub ( super ) fn set_exit ( & mut self , reason : T :: Exit ) {
169
+ self . status = Status :: Stop ( StopReason :: Exit ( reason) ) ;
111
170
}
112
171
113
172
/// Return whether a break reason has been set already. This function will return `false` after
@@ -118,31 +177,34 @@ impl<T: EventClosure> EventDispatcher<T> {
118
177
119
178
/// Run the event loop for this handler.
120
179
///
121
- /// The event loop will continue indefinitely unless [`EventDispatcher::set_break`] is called.
122
- pub ( super ) fn event_loop ( & mut self , state : & mut T ) -> T :: Break {
180
+ /// The event loop will continue indefinitely unless you call [`EventDispatcher::set_break`] or
181
+ /// [`EventDispatcher::set_exit`].
182
+ pub ( super ) fn event_loop ( & mut self , state : & mut T ) -> StopReason < T > {
123
183
loop {
124
184
if let Ok ( ids) = self . poll_set . poll ( ) {
125
185
for EventId ( id) in ids {
126
186
self . callbacks [ id] ( state, self ) ;
127
187
128
- if let Some ( break_reason ) = self . check_break ( ) {
129
- return break_reason ;
188
+ if let Some ( reason ) = self . status . take_break ( ) {
189
+ return StopReason :: Break ( reason ) ;
130
190
}
131
191
}
132
- }
133
-
134
- if let Some ( break_reason) = self . check_break ( ) {
135
- return break_reason;
192
+ if let Some ( reason) = self . status . take_exit ( ) {
193
+ return StopReason :: Exit ( reason) ;
194
+ }
195
+ } else {
196
+ // FIXME: maybe we shout return the IO error instead.
197
+ if let Some ( reason) = self . status . take_stop ( ) {
198
+ return reason;
199
+ }
136
200
}
137
201
}
138
202
}
139
203
140
- pub ( super ) fn check_break ( & mut self ) -> Option < T :: Break > {
141
- // This is OK as we are swapping `Continue(())` by other `Continue(())` if the status is
142
- // not `Break`.
143
- match std:: mem:: replace ( & mut self . status , ControlFlow :: Continue ( ( ) ) ) {
144
- ControlFlow :: Continue ( ( ) ) => None ,
145
- ControlFlow :: Break ( reason) => Some ( reason) ,
204
+ /// Unregister all the handlers created by the dispatcher.
205
+ pub ( super ) fn unregister_handlers ( self ) {
206
+ for handler in self . signal_handlers {
207
+ handler. unregister ( ) ;
146
208
}
147
209
}
148
210
}
0 commit comments