use crate::{AtomicBool, AtomicOrdering}; use std::sync::atomic::AtomicU32; static ORPHAN_CHECK_RUNNING: AtomicBool = AtomicBool::new(false); static ORPHAN_RECHECK_REQUESTED: AtomicBool = AtomicBool::new(false); static ORPHAN_RECHECK_FROM_HEIGHT: AtomicU32 = AtomicU32::new(0); fn store_earliest_recheck_height(incoming_height: u32) { let mut current = ORPHAN_RECHECK_FROM_HEIGHT.load(AtomicOrdering::SeqCst); while current == 0 || incoming_height < current { match ORPHAN_RECHECK_FROM_HEIGHT.compare_exchange( current, incoming_height, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst, ) { Ok(_) => return, Err(next_current) => current = next_current, } } } pub fn try_begin_orphan_check() -> bool { if ORPHAN_CHECK_RUNNING .compare_exchange(false, true, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst) .is_err() { return false; } ORPHAN_RECHECK_REQUESTED.store(false, AtomicOrdering::SeqCst); ORPHAN_RECHECK_FROM_HEIGHT.store(0, AtomicOrdering::SeqCst); true } pub fn request_orphan_recheck(incoming_height: u32) { store_earliest_recheck_height(incoming_height); ORPHAN_RECHECK_REQUESTED.store(true, AtomicOrdering::SeqCst); } pub fn take_orphan_recheck_height() -> Option { if !ORPHAN_RECHECK_REQUESTED.swap(false, AtomicOrdering::SeqCst) { return None; } Some(ORPHAN_RECHECK_FROM_HEIGHT.swap(0, AtomicOrdering::SeqCst)) } pub fn finish_orphan_check() { ORPHAN_CHECK_RUNNING.store(false, AtomicOrdering::SeqCst); }