use crate::state::{SearchCell, SnapshotCell, latest_snapshot};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::JoinHandle;
use std::time::Duration;
const SEARCH_POLL: Duration = Duration::from_millis(50);
pub struct Searcher {
snap: SnapshotCell,
asks: SearchCell,
}
impl Searcher {
pub(crate) fn new(snap: SnapshotCell, asks: SearchCell) -> Self {
Self { snap, asks }
}
pub fn pass(&self) -> bool {
let Some((seq, text)) = self.asks.pending() else {
return false;
};
let snap = latest_snapshot(&self.snap);
let found = super::run(&snap, &text, &|| self.asks.seq() == seq);
self.asks.publish(seq, found);
self.asks.seq() == seq
}
pub fn spawn(self) -> SearchThread {
let stop = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&stop);
let handle = std::thread::spawn(move || {
while !flag.load(Ordering::Relaxed) {
self.pass();
std::thread::park_timeout(SEARCH_POLL);
}
});
SearchThread {
stop,
handle: Some(handle),
}
}
}
pub struct SearchThread {
stop: Arc<AtomicBool>,
handle: Option<JoinHandle<()>>,
}
impl Drop for SearchThread {
fn drop(&mut self) {
self.stop.store(true, Ordering::Relaxed);
if let Some(handle) = self.handle.take() {
handle.thread().unpark();
let _ = handle.join();
}
}
}