codegame 0.6.0

CodeGame framework
Documentation
use super::*;

use std::sync::atomic::{AtomicUsize, Ordering};

pub struct BackgroundGameProcessor<G: Game> {
    ticks_to_process: Arc<AtomicUsize>,
    thread: std::thread::JoinHandle<()>,
    phantom_data: PhantomData<G>,
}

impl<G: Game> BackgroundGameProcessor<G> {
    pub fn new(
        mut processor: GameProcessor<G>,
        mut tick_handler: impl FnMut(&G, Vec<G::Event>) + Send + 'static,
        custom_data_handler: Option<impl Fn(usize, G::CustomData) + Send + 'static>,
    ) -> Self {
        let ticks_to_process = Arc::new(AtomicUsize::new(0));
        let thread = std::thread::spawn({
            let ticks_to_process = ticks_to_process.clone();
            move || {
                while !processor.finished() {
                    loop {
                        let ticks = ticks_to_process.load(Ordering::SeqCst);
                        if ticks > 0
                            && ticks_to_process.compare_and_swap(ticks, ticks - 1, Ordering::SeqCst)
                                == ticks
                        {
                            break;
                        }
                        std::thread::park();
                    }
                    let events =
                        processor.process_tick(custom_data_handler.as_ref().map(|f| f as _));
                    tick_handler(processor.game(), events);
                }
            }
        });
        Self {
            ticks_to_process,
            thread,
            phantom_data: PhantomData,
        }
    }
    pub fn proceed(&mut self, max_ticks: usize) {
        self.ticks_to_process.store(max_ticks, Ordering::SeqCst);
        self.thread.thread().unpark();
    }
}