@@ -41,137 +41,177 @@ impl Event {
41
41
}
42
42
}
43
43
44
- /// What happens after the handler is called?
45
- #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
46
- enum AfterHandle {
47
- /// The handler is removed (once).
48
- Remove ,
49
-
50
- /// Nothing is done (regular).
51
- DoNothing ,
44
+ /// What to do with the pending handler when resolving it?
45
+ enum Pending < Event : Tag , Window : Tag > {
46
+ Unlisten ( EventHandler ) ,
47
+ Listen ( EventHandler , Event , Handler < Window > ) ,
48
+ Trigger ( Event , Option < Window > , Option < String > ) ,
52
49
}
53
50
54
51
/// Stored in [`Listeners`] to be called upon when the event that stored it is triggered.
55
52
struct Handler < Window : Tag > {
56
53
window : Option < Window > ,
57
- callback : Box < dyn Fn ( Event ) -> AfterHandle + Send > ,
54
+ callback : Box < dyn Fn ( Event ) + Send > ,
58
55
}
59
56
60
57
/// A collection of handlers. Multiple handlers can represent the same event.
61
58
type Handlers < Event , Window > = HashMap < Event , HashMap < EventHandler , Handler < Window > > > ;
62
59
63
- #[ derive( Clone ) ]
64
- pub ( crate ) struct Listeners < Event : Tag , Window : Tag > {
65
- inner : Arc < Mutex < Handlers < Event , Window > > > ,
60
+ /// Holds event handlers and pending event handlers, along with the salts associating them.
61
+ struct InnerListeners < Event : Tag , Window : Tag > {
62
+ handlers : Mutex < Handlers < Event , Window > > ,
63
+ pending : Mutex < Vec < Pending < Event , Window > > > ,
66
64
function_name : Uuid ,
67
65
listeners_object_name : Uuid ,
68
66
queue_object_name : Uuid ,
69
67
}
70
68
71
- impl < E : Tag , L : Tag > Default for Listeners < E , L > {
69
+ /// A self-contained event manager.
70
+ pub ( crate ) struct Listeners < Event : Tag , Window : Tag > {
71
+ inner : Arc < InnerListeners < Event , Window > > ,
72
+ }
73
+
74
+ impl < Event : Tag , Window : Tag > Default for Listeners < Event , Window > {
72
75
fn default ( ) -> Self {
73
76
Self {
74
- inner : Arc :: new ( Mutex :: default ( ) ) ,
75
- function_name : Uuid :: new_v4 ( ) ,
76
- listeners_object_name : Uuid :: new_v4 ( ) ,
77
- queue_object_name : Uuid :: new_v4 ( ) ,
77
+ inner : Arc :: new ( InnerListeners {
78
+ handlers : Mutex :: default ( ) ,
79
+ pending : Mutex :: default ( ) ,
80
+ function_name : Uuid :: new_v4 ( ) ,
81
+ listeners_object_name : Uuid :: new_v4 ( ) ,
82
+ queue_object_name : Uuid :: new_v4 ( ) ,
83
+ } ) ,
84
+ }
85
+ }
86
+ }
87
+
88
+ impl < Event : Tag , Window : Tag > Clone for Listeners < Event , Window > {
89
+ fn clone ( & self ) -> Self {
90
+ Self {
91
+ inner : self . inner . clone ( ) ,
78
92
}
79
93
}
80
94
}
81
95
82
- impl < E : Tag , L : Tag > Listeners < E , L > {
96
+ impl < Event : Tag , Window : Tag > Listeners < Event , Window > {
83
97
/// Randomly generated function name to represent the JavaScript event function.
84
98
pub ( crate ) fn function_name ( & self ) -> String {
85
- self . function_name . to_string ( )
99
+ self . inner . function_name . to_string ( )
86
100
}
87
101
88
102
/// Randomly generated listener object name to represent the JavaScript event listener object.
89
103
pub ( crate ) fn listeners_object_name ( & self ) -> String {
90
- self . function_name . to_string ( )
104
+ self . inner . listeners_object_name . to_string ( )
91
105
}
92
106
93
107
/// Randomly generated queue object name to represent the JavaScript event queue object.
94
108
pub ( crate ) fn queue_object_name ( & self ) -> String {
95
- self . queue_object_name . to_string ( )
109
+ self . inner . queue_object_name . to_string ( )
96
110
}
97
111
98
- fn listen_internal < F > ( & self , event : E , window : Option < L > , handler : F ) -> EventHandler
99
- where
100
- F : Fn ( Event ) -> AfterHandle + Send + ' static ,
101
- {
102
- let id = EventHandler ( Uuid :: new_v4 ( ) ) ;
103
-
112
+ /// Insert a pending event action to the queue.
113
+ fn insert_pending ( & self , action : Pending < Event , Window > ) {
104
114
self
105
115
. inner
116
+ . pending
106
117
. lock ( )
107
- . expect ( "poisoned event mutex" )
108
- . entry ( event)
109
- . or_default ( )
110
- . insert (
111
- id,
112
- Handler {
113
- window,
114
- callback : Box :: new ( handler) ,
115
- } ,
116
- ) ;
118
+ . expect ( "poisoned pending event queue" )
119
+ . push ( action)
120
+ }
117
121
118
- id
122
+ /// Finish all pending event actions.
123
+ fn flush_pending ( & self ) {
124
+ let pending = {
125
+ let mut lock = self
126
+ . inner
127
+ . pending
128
+ . lock ( )
129
+ . expect ( "poisoned pending event queue" ) ;
130
+ std:: mem:: take ( & mut * lock)
131
+ } ;
132
+
133
+ for action in pending {
134
+ match action {
135
+ Pending :: Unlisten ( id) => self . unlisten ( id) ,
136
+ Pending :: Listen ( id, event, handler) => self . listen_ ( id, event, handler) ,
137
+ Pending :: Trigger ( event, window, payload) => self . trigger ( event, window, payload) ,
138
+ }
139
+ }
140
+ }
141
+
142
+ fn listen_ ( & self , id : EventHandler , event : Event , handler : Handler < Window > ) {
143
+ match self . inner . handlers . try_lock ( ) {
144
+ Err ( _) => self . insert_pending ( Pending :: Listen ( id, event, handler) ) ,
145
+ Ok ( mut lock) => {
146
+ lock. entry ( event) . or_default ( ) . insert ( id, handler) ;
147
+ }
148
+ }
119
149
}
120
150
121
151
/// Adds an event listener for JS events.
122
- pub ( crate ) fn listen < F > ( & self , event : E , window : Option < L > , handler : F ) -> EventHandler
123
- where
124
- F : Fn ( Event ) + Send + ' static ,
125
- {
126
- self . listen_internal ( event, window, move |event| {
127
- handler ( event) ;
128
- AfterHandle :: DoNothing
129
- } )
152
+ pub ( crate ) fn listen < F : Fn ( self :: Event ) + Send + ' static > (
153
+ & self ,
154
+ event : Event ,
155
+ window : Option < Window > ,
156
+ handler : F ,
157
+ ) -> EventHandler {
158
+ let id = EventHandler ( Uuid :: new_v4 ( ) ) ;
159
+ let handler = Handler {
160
+ window,
161
+ callback : Box :: new ( handler) ,
162
+ } ;
163
+
164
+ self . listen_ ( id, event, handler) ;
165
+
166
+ id
130
167
}
131
168
132
169
/// Listen to a JS event and immediately unlisten.
133
- pub ( crate ) fn once < F : Fn ( Event ) + Send + ' static > (
170
+ pub ( crate ) fn once < F : Fn ( self :: Event ) + Send + ' static > (
134
171
& self ,
135
- event : E ,
136
- window : Option < L > ,
172
+ event : Event ,
173
+ window : Option < Window > ,
137
174
handler : F ,
138
175
) -> EventHandler {
139
- self . listen_internal ( event, window, move |event| {
176
+ let self_ = self . clone ( ) ;
177
+ self . listen ( event, window, move |event| {
178
+ self_. unlisten ( event. id ) ;
140
179
handler ( event) ;
141
- AfterHandle :: Remove
142
180
} )
143
181
}
144
182
145
183
/// Removes an event listener.
146
184
pub ( crate ) fn unlisten ( & self , handler_id : EventHandler ) {
147
- self
148
- . inner
149
- . lock ( )
150
- . expect ( "poisoned event mutex" )
151
- . values_mut ( )
152
- . for_each ( |handler| {
185
+ match self . inner . handlers . try_lock ( ) {
186
+ Err ( _) => self . insert_pending ( Pending :: Unlisten ( handler_id) ) ,
187
+ Ok ( mut lock) => lock. values_mut ( ) . for_each ( |handler| {
153
188
handler. remove ( & handler_id) ;
154
- } )
189
+ } ) ,
190
+ }
155
191
}
156
192
157
193
/// Triggers the given global event with its payload.
158
- pub ( crate ) fn trigger ( & self , event : E , window : Option < L > , data : Option < String > ) {
159
- if let Some ( handlers ) = self
160
- . inner
161
- . lock ( )
162
- . expect ( "poisoned event mutex" )
163
- . get_mut ( & event)
164
- {
165
- handlers . retain ( | & id , handler| {
166
- if window . is_none ( ) || window == handler . window {
167
- let data = data . clone ( ) ;
168
- let payload = Event { id, data } ;
169
- ( handler . callback ) ( payload ) != AfterHandle :: Remove
170
- } else {
171
- // skip and retain all handlers specifying a different window
172
- true
194
+ pub ( crate ) fn trigger ( & self , event : Event , window : Option < Window > , payload : Option < String > ) {
195
+ let mut maybe_pending = false ;
196
+ match self . inner . handlers . try_lock ( ) {
197
+ Err ( _ ) => self . insert_pending ( Pending :: Trigger ( event , window , payload ) ) ,
198
+ Ok ( lock ) => {
199
+ if let Some ( handlers ) = lock . get ( & event) {
200
+ for ( & id , handler ) in handlers {
201
+ if window . is_none ( ) || window == handler. window {
202
+ maybe_pending = true ;
203
+ ( handler . callback ) ( self :: Event {
204
+ id,
205
+ data : payload . clone ( ) ,
206
+ } )
207
+ }
208
+ }
173
209
}
174
- } )
210
+ }
211
+ }
212
+
213
+ if maybe_pending {
214
+ self . flush_pending ( ) ;
175
215
}
176
216
}
177
217
}
@@ -199,7 +239,7 @@ mod test {
199
239
listeners. listen( e, None , event_fn) ;
200
240
201
241
// lock mutex
202
- let l = listeners. inner. lock( ) . unwrap( ) ;
242
+ let l = listeners. inner. handlers . lock( ) . unwrap( ) ;
203
243
204
244
// check if the generated key is in the map
205
245
assert_eq!( l. contains_key( & key) , true ) ;
@@ -215,7 +255,7 @@ mod test {
215
255
listeners. listen( e, None , event_fn) ;
216
256
217
257
// lock mutex
218
- let mut l = listeners. inner. lock( ) . unwrap( ) ;
258
+ let mut l = listeners. inner. handlers . lock( ) . unwrap( ) ;
219
259
220
260
// check if l contains key
221
261
if l. contains_key( & key) {
@@ -243,7 +283,7 @@ mod test {
243
283
listeners. trigger( e, None , Some ( d) ) ;
244
284
245
285
// lock the mutex
246
- let l = listeners. inner. lock( ) . unwrap( ) ;
286
+ let l = listeners. inner. handlers . lock( ) . unwrap( ) ;
247
287
248
288
// assert that the key is contained in the listeners map
249
289
assert!( l. contains_key( & key) ) ;
0 commit comments