@@ -252,12 +252,21 @@ impl<'a, CL: Deref<Target = ChainListener + 'a> + 'a> BlockNotifier<'a, CL> {
252
252
}
253
253
254
254
/// Register the given listener to receive events.
255
- // TODO: unregister
256
255
pub fn register_listener ( & self , listener : CL ) {
257
256
let mut vec = self . listeners . lock ( ) . unwrap ( ) ;
258
257
vec. push ( listener) ;
259
258
}
260
259
260
+ /// Unregister the given listener to no longer
261
+ /// receive events.
262
+ ///
263
+ /// If the same listener is registered multiple times, unregistering
264
+ /// will remove ALL occurrences of that listener.
265
+ pub fn unregister_listener ( & self , listener : CL ) {
266
+ let mut vec = self . listeners . lock ( ) . unwrap ( ) ;
267
+ vec. retain ( |item| !std:: ptr:: eq ( & ( * * item) as * const _ , & ( * listener) as * const _ ) ) ;
268
+ }
269
+
261
270
/// Notify listeners that a block was connected given a full, unfiltered block.
262
271
///
263
272
/// Handles re-scanning the block and calling block_connected again if listeners register new
@@ -376,3 +385,58 @@ impl ChainWatchInterfaceUtil {
376
385
watched. does_match_tx ( tx)
377
386
}
378
387
}
388
+
389
+ #[ cfg( test) ]
390
+ mod tests {
391
+ use ln:: functional_test_utils:: { create_node_cfgs} ;
392
+ use super :: { BlockNotifier , ChainListener } ;
393
+
394
+ #[ test]
395
+ fn register_listener_test ( ) {
396
+ let node_cfgs = create_node_cfgs ( 1 ) ;
397
+ let block_notifier: BlockNotifier < & dyn ChainListener > = BlockNotifier :: new ( node_cfgs[ 0 ] . chain_monitor . clone ( ) ) ;
398
+ let listener = & node_cfgs[ 0 ] . chan_monitor . simple_monitor as & ChainListener ;
399
+ block_notifier. register_listener ( listener) ;
400
+ let vec = block_notifier. listeners . lock ( ) . unwrap ( ) ;
401
+ assert_eq ! ( vec. len( ) , 1 ) ;
402
+ let item = vec. first ( ) . clone ( ) . unwrap ( ) ;
403
+ assert ! ( std:: ptr:: eq( & ( * * item) as * const _, & ( * listener) as * const _) ) ;
404
+ }
405
+
406
+ #[ test]
407
+ fn unregister_single_listener_test ( ) {
408
+ let node_cfgs = create_node_cfgs ( 2 ) ;
409
+ let block_notifier: BlockNotifier < & dyn ChainListener > = BlockNotifier :: new ( node_cfgs[ 0 ] . chain_monitor . clone ( ) ) ;
410
+ let listener1 = & node_cfgs[ 0 ] . chan_monitor . simple_monitor as & ChainListener ;
411
+ let listener2 = & node_cfgs[ 1 ] . chan_monitor . simple_monitor as & ChainListener ;
412
+ block_notifier. register_listener ( listener1) ;
413
+ block_notifier. register_listener ( listener2) ;
414
+ let vec = block_notifier. listeners . lock ( ) . unwrap ( ) ;
415
+ assert_eq ! ( vec. len( ) , 2 ) ;
416
+ drop ( vec) ;
417
+ block_notifier. unregister_listener ( listener1) ;
418
+ let vec = block_notifier. listeners . lock ( ) . unwrap ( ) ;
419
+ assert_eq ! ( vec. len( ) , 1 ) ;
420
+ let item = vec. first ( ) . clone ( ) . unwrap ( ) ;
421
+ assert ! ( std:: ptr:: eq( & ( * * item) as * const _, & ( * listener2) as * const _) ) ;
422
+ }
423
+
424
+ #[ test]
425
+ fn unregister_multiple_of_the_same_listeners_test ( ) {
426
+ let node_cfgs = create_node_cfgs ( 2 ) ;
427
+ let block_notifier: BlockNotifier < & dyn ChainListener > = BlockNotifier :: new ( node_cfgs[ 0 ] . chain_monitor . clone ( ) ) ;
428
+ let listener1 = & node_cfgs[ 0 ] . chan_monitor . simple_monitor as & ChainListener ;
429
+ let listener2 = & node_cfgs[ 1 ] . chan_monitor . simple_monitor as & ChainListener ;
430
+ block_notifier. register_listener ( listener1) ;
431
+ block_notifier. register_listener ( listener1) ;
432
+ block_notifier. register_listener ( listener2) ;
433
+ let vec = block_notifier. listeners . lock ( ) . unwrap ( ) ;
434
+ assert_eq ! ( vec. len( ) , 3 ) ;
435
+ drop ( vec) ;
436
+ block_notifier. unregister_listener ( listener1) ;
437
+ let vec = block_notifier. listeners . lock ( ) . unwrap ( ) ;
438
+ assert_eq ! ( vec. len( ) , 1 ) ;
439
+ let item = vec. first ( ) . clone ( ) . unwrap ( ) ;
440
+ assert ! ( std:: ptr:: eq( & ( * * item) as * const _, & ( * listener2) as * const _) ) ;
441
+ }
442
+ }
0 commit comments