base-coroutine 0.2.0

A fast and safe implementation of stackful coroutines with scheduler which supports preemptive scheduling.
Documentation
use once_cell::sync::Lazy;
use std::sync::atomic::{AtomicUsize, Ordering};

pub struct IdGenerator {}

static mut COROUTINE_ID: Lazy<AtomicUsize> = Lazy::new(|| AtomicUsize::new(1));

static mut SCHEDULER_ID: Lazy<AtomicUsize> = Lazy::new(|| AtomicUsize::new(1));

impl IdGenerator {
    fn reset() {
        unsafe {
            COROUTINE_ID.store(1, Ordering::SeqCst);
            SCHEDULER_ID.store(1, Ordering::SeqCst);
        }
    }

    pub fn next_coroutine_id() -> usize {
        unsafe {
            let val = COROUTINE_ID.fetch_add(1, Ordering::SeqCst);
            if val == usize::MAX {
                COROUTINE_ID.store(1, Ordering::SeqCst);
            }
            val
        }
    }

    pub fn next_scheduler_id() -> usize {
        unsafe {
            let val = SCHEDULER_ID.fetch_add(1, Ordering::SeqCst);
            if val == usize::MAX {
                COROUTINE_ID.store(1, Ordering::SeqCst);
            }
            val
        }
    }
}

#[cfg(test)]
mod tests {
    use super::IdGenerator;

    #[test]
    fn test() {
        IdGenerator::reset();
        assert_eq!(1, IdGenerator::next_coroutine_id());
        assert_eq!(2, IdGenerator::next_coroutine_id());
        assert_eq!(3, IdGenerator::next_coroutine_id());
        IdGenerator::reset();
        assert_eq!(1, IdGenerator::next_scheduler_id());
        assert_eq!(2, IdGenerator::next_scheduler_id());
        assert_eq!(3, IdGenerator::next_scheduler_id());
    }
}