@@ -13,7 +13,8 @@ lazy_static::lazy_static! {
13
13
static ref SAMPLING_TIMEOUT : Duration = Duration :: from_millis( 50 ) ;
14
14
}
15
15
16
- /// Event returned by [`NodeListener::for_each()`] when some network or signal is received.
16
+ /// Event returned by [`NodeListener::for_each()`] and [`NodeListener::for_each_async()`]
17
+ /// when some network event or signal is received.
17
18
pub enum NodeEvent < ' a , S > {
18
19
/// The `NodeEvent` is an event that comes from the network.
19
20
/// See [`NetEvent`] to know about the different network events.
@@ -26,6 +27,15 @@ pub enum NodeEvent<'a, S> {
26
27
Signal ( S ) ,
27
28
}
28
29
30
+ impl < ' a , S : std:: fmt:: Debug > std:: fmt:: Debug for NodeEvent < ' a , S > {
31
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
32
+ match self {
33
+ NodeEvent :: Network ( net_event) => write ! ( f, "NodeEvent::Network({:?})" , net_event) ,
34
+ NodeEvent :: Signal ( signal) => write ! ( f, "NodeEvent::Signal({:?})" , signal) ,
35
+ }
36
+ }
37
+ }
38
+
29
39
impl < ' a , S > NodeEvent < ' a , S > {
30
40
/// Assume the event is a [`NodeEvent::Network`], panics if not.
31
41
pub fn network ( self ) -> NetEvent < ' a > {
@@ -171,6 +181,19 @@ impl StoredNetEvent {
171
181
}
172
182
}
173
183
184
+ struct SendableEventCallback < S > ( Arc < Mutex < dyn FnMut ( NodeEvent < S > ) > > ) ;
185
+
186
+ // This struct is used to allow passing no Sendable objects into the listener jobs.
187
+ // Although it is unsafe, it is safely handled by the for_each / for_each_async functions.
188
+ // (see its internal comments)
189
+ unsafe impl < S > Send for SendableEventCallback < S > { }
190
+
191
+ impl < S > Clone for SendableEventCallback < S > {
192
+ fn clone ( & self ) -> Self {
193
+ Self ( self . 0 . clone ( ) )
194
+ }
195
+ }
196
+
174
197
/// Main entity to manipulates the network and signal events easily.
175
198
/// The node run asynchronously.
176
199
pub struct NodeListener < S : Send + ' static > {
@@ -209,15 +232,10 @@ impl<S: Send + 'static> NodeListener<S> {
209
232
210
233
/// Iterate indefinitely over all generated `NetEvent`.
211
234
/// This function will work until [`NodeHandler::stop`] was called.
212
- /// A `NodeTask` representing the asynchronous job is returned.
213
- /// Destroying this object will result in blocking the current thread until
214
- /// [`NodeHandler::stop`] was called.
215
235
///
216
- /// In order to allow the node working asynchronously, you can move the `NodeTask` to a
217
- /// an object with a longer lifetime.
218
- ///
219
- /// # Examples
220
- /// **Synchronous** usage:
236
+ /// Note that any events generated before calling this function (e.g. some connection was done)
237
+ /// will be storage and offered once you call `for_each()`.
238
+ /// # Example
221
239
/// ```
222
240
/// use message_io::node::{self, NodeEvent};
223
241
/// use message_io::network::Transport;
@@ -230,12 +248,27 @@ impl<S: Send + 'static> NodeListener<S> {
230
248
/// NodeEvent::Network(net_event) => { /* Your logic here */ },
231
249
/// NodeEvent::Signal(_) => handler.stop(),
232
250
/// });
233
- /// // Blocked here until handler.stop() was called (1 sec) because the returned value
234
- /// // of for_each() is not used (it is dropped just after called the method).
251
+ /// // Blocked here until handler.stop() was called (1 sec).
235
252
/// println!("Node is stopped");
236
253
/// ```
254
+ pub fn for_each ( self , event_callback : impl FnMut ( NodeEvent < S > ) + ' static ) {
255
+ let sendable_callback = SendableEventCallback ( Arc :: new ( Mutex :: new ( event_callback) ) ) ;
256
+ let mut task = self . for_each_impl ( sendable_callback) ;
257
+
258
+ // Although the event_callback is not sync, we ensure with this wait() that no more events
259
+ // will be processed when the control is returned to the user.
260
+ task. wait ( ) ;
261
+ }
262
+
263
+ /// Similar to [`NodeListener::for_each()`] but it returns the control to the user
264
+ /// after call it. The events would be processed asynchronously.
265
+ /// A `NodeTask` representing this asynchronous job is returned.
266
+ /// Destroying this object will result in blocking the current thread until
267
+ /// [`NodeHandler::stop`] was called.
268
+ ///
269
+ /// In order to allow the node working asynchronously, you can move the `NodeTask` to a
270
+ /// an object with a longer lifetime.
237
271
///
238
- /// **Asynchronous** usage:
239
272
/// ```
240
273
/// use message_io::node::{self, NodeEvent};
241
274
/// use message_io::network::Transport;
@@ -248,32 +281,36 @@ impl<S: Send + 'static> NodeListener<S> {
248
281
/// NodeEvent::Network(net_event) => { /* Your logic here */ },
249
282
/// NodeEvent::Signal(_) => handler.stop(),
250
283
/// });
251
- /// // for_each () will act asynchronous during 'task' lifetime.
284
+ /// // for_each_async () will act asynchronous during 'task' lifetime.
252
285
///
253
286
/// // ...
254
287
/// println!("Node is running");
255
288
/// // ...
256
289
///
257
290
/// drop(task); // Blocked here until handler.stop() was called (1 sec).
258
- /// //also task.wait(); can be called doing the same (but taking a mutable reference).
291
+ /// // Also task.wait(); can be called doing the same (but taking a mutable reference).
259
292
///
260
293
/// println!("Node is stopped");
261
294
/// ```
262
- /// Note that any events generated before calling this function will be storage
263
- /// and offered once you call `for_each()`.
264
- pub fn for_each (
265
- mut self ,
295
+ pub fn for_each_async (
296
+ self ,
266
297
event_callback : impl FnMut ( NodeEvent < S > ) + Send + ' static ,
267
298
) -> NodeTask {
299
+ let sendable_callback = SendableEventCallback ( Arc :: new ( Mutex :: new ( event_callback) ) ) ;
300
+
301
+ // The signature of this functions add the `Send` to the `event_callback` that
302
+ // `SendableEventCallback` removed, so the usage is safe.
303
+ self . for_each_impl ( sendable_callback)
304
+ }
305
+
306
+ fn for_each_impl ( mut self , multiplexed : SendableEventCallback < S > ) -> NodeTask {
268
307
// Stop cache events
269
308
self . cache_running . store ( false , Ordering :: Relaxed ) ;
270
309
let ( mut network_processor, mut cache) = self . network_cache_thread . join ( ) ;
271
310
272
- let multiplexed = Arc :: new ( Mutex :: new ( event_callback) ) ;
273
-
274
311
// To avoid processing stops while the node is configuring,
275
312
// the user callback locked until the function ends.
276
- let _locked = multiplexed. lock ( ) . expect ( OTHER_THREAD_ERR ) ;
313
+ let _locked = multiplexed. 0 . lock ( ) . expect ( OTHER_THREAD_ERR ) ;
277
314
278
315
let network_thread = {
279
316
let multiplexed = multiplexed. clone ( ) ;
@@ -282,7 +319,7 @@ impl<S: Send + 'static> NodeListener<S> {
282
319
NamespacedThread :: spawn ( "node-network-thread" , move || {
283
320
// Dispatch the catched events first.
284
321
while let Some ( event) = cache. pop_front ( ) {
285
- let mut event_callback = multiplexed. lock ( ) . expect ( OTHER_THREAD_ERR ) ;
322
+ let mut event_callback = multiplexed. 0 . lock ( ) . expect ( OTHER_THREAD_ERR ) ;
286
323
let net_event = event. borrow ( ) ;
287
324
log:: trace!( "Read from cache {:?}" , net_event) ;
288
325
event_callback ( NodeEvent :: Network ( net_event) ) ;
@@ -293,7 +330,7 @@ impl<S: Send + 'static> NodeListener<S> {
293
330
294
331
while running. load ( Ordering :: Relaxed ) {
295
332
network_processor. process_poll_event ( Some ( * SAMPLING_TIMEOUT ) , |net_event| {
296
- let mut event_callback = multiplexed. lock ( ) . expect ( OTHER_THREAD_ERR ) ;
333
+ let mut event_callback = multiplexed. 0 . lock ( ) . expect ( OTHER_THREAD_ERR ) ;
297
334
if running. load ( Ordering :: Relaxed ) {
298
335
event_callback ( NodeEvent :: Network ( net_event) ) ;
299
336
}
@@ -310,7 +347,7 @@ impl<S: Send + 'static> NodeListener<S> {
310
347
NamespacedThread :: spawn ( "node-signal-thread" , move || {
311
348
while running. load ( Ordering :: Relaxed ) {
312
349
if let Some ( signal) = signal_receiver. receive_timeout ( * SAMPLING_TIMEOUT ) {
313
- let mut event_callback = multiplexed. lock ( ) . expect ( OTHER_THREAD_ERR ) ;
350
+ let mut event_callback = multiplexed. 0 . lock ( ) . expect ( OTHER_THREAD_ERR ) ;
314
351
if running. load ( Ordering :: Relaxed ) {
315
352
event_callback ( NodeEvent :: Signal ( signal) ) ;
316
353
}
@@ -329,11 +366,11 @@ impl<S: Send + 'static> Drop for NodeListener<S> {
329
366
}
330
367
}
331
368
332
- /// Entity used to ensure the lifetime of [`NodeListener::for_each ()`] call.
369
+ /// Entity used to ensure the lifetime of [`NodeListener::for_each_async ()`] call.
333
370
/// The node will process events asynchronously while this entity lives.
334
371
/// The destruction of this entity will block until the task is finished.
335
- /// If you want to "unblock" the thread that drops this entity call to:
336
- /// [`NodeHandler::stop()`]
372
+ /// If you want to "unblock" the thread that drops this entity call to
373
+ /// [`NodeHandler::stop()`] before or from another thread.
337
374
pub struct NodeTask {
338
375
network_thread : NamespacedThread < ( ) > ,
339
376
signal_thread : NamespacedThread < ( ) > ,
@@ -385,7 +422,7 @@ mod tests {
385
422
let checked = Arc :: new ( AtomicBool :: new ( false ) ) ;
386
423
let inner_checked = checked. clone ( ) ;
387
424
let inner_handler = handler. clone ( ) ;
388
- let _node_task = listener. for_each ( move |event| match event. signal ( ) {
425
+ let _node_task = listener. for_each_async ( move |event| match event. signal ( ) {
389
426
"stop" => inner_handler. stop ( ) ,
390
427
"check" => inner_checked. store ( true , Ordering :: Relaxed ) ,
391
428
_ => unreachable ! ( ) ,
@@ -406,7 +443,7 @@ mod tests {
406
443
handler. signals ( ) . send_with_timer ( ( ) , Duration :: from_millis ( 1000 ) ) ;
407
444
408
445
let inner_handler = handler. clone ( ) ;
409
- listener. for_each ( move |_| inner_handler. stop ( ) ) . wait ( ) ;
446
+ listener. for_each_async ( move |_| inner_handler. stop ( ) ) . wait ( ) ;
410
447
411
448
assert ! ( !handler. is_running( ) ) ;
412
449
}
@@ -418,7 +455,7 @@ mod tests {
418
455
handler. signals ( ) . send_with_timer ( ( ) , Duration :: from_millis ( 1000 ) ) ;
419
456
420
457
let inner_handler = handler. clone ( ) ;
421
- let mut task = listener. for_each ( move |_| inner_handler. stop ( ) ) ;
458
+ let mut task = listener. for_each_async ( move |_| inner_handler. stop ( ) ) ;
422
459
assert ! ( handler. is_running( ) ) ;
423
460
task. wait ( ) ;
424
461
assert ! ( !handler. is_running( ) ) ;
0 commit comments