Skip to content

Commit 9bfcac6

Browse files
committed
add functionality for BlockNotifier to unregister a previously registered listener, in order to no longer receive events
1 parent fc03ab1 commit 9bfcac6

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

lightning/src/chain/chaininterface.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
1919
use std::collections::HashSet;
2020
use std::ops::Deref;
2121
use std::marker::PhantomData;
22+
use std::ptr::eq as ptr_eq;
2223

2324
/// Used to give chain error details upstream
2425
pub enum ChainError {
@@ -252,12 +253,21 @@ impl<'a, CL: Deref<Target = ChainListener + 'a> + 'a> BlockNotifier<'a, CL> {
252253
}
253254

254255
/// Register the given listener to receive events.
255-
// TODO: unregister
256256
pub fn register_listener(&self, listener: CL) {
257257
let mut vec = self.listeners.lock().unwrap();
258258
vec.push(listener);
259259
}
260260

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

lightning/src/ln/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ mod onion_utils;
2727
mod wire;
2828

2929
#[cfg(test)]
30-
#[macro_use] mod functional_test_utils;
30+
#[macro_use]
31+
pub(crate) mod functional_test_utils;
3132
#[cfg(test)]
3233
mod functional_tests;
3334
#[cfg(test)]

0 commit comments

Comments
 (0)