xlog-cuda 0.9.2

CUDA kernel provider, buffers, and interop for XLOG
use std::sync::{Arc, Barrier};
use std::thread;

use xlog_cuda::device_runtime::{AllocTag, StreamId, XlogDeviceRuntime};

fn runtime_or_skip() -> Option<&'static XlogDeviceRuntime> {
    match XlogDeviceRuntime::try_get(0) {
        Ok(runtime) => Some(runtime),
        Err(err) => {
            eprintln!("Skipping: CUDA runtime unavailable: {}", err);
            None
        }
    }
}

#[test]
fn get_returns_same_singleton_for_same_ordinal() {
    let Some(first) = runtime_or_skip() else {
        return;
    };
    let second = XlogDeviceRuntime::try_get(0).expect("runtime should stay available");

    assert!(std::ptr::eq(first, second));
    assert_eq!(first.device_ordinal(), 0);
    assert_eq!(second.device_ordinal(), 0);
}

#[test]
fn concurrent_get_returns_same_singleton() {
    let Some(expected) = runtime_or_skip() else {
        return;
    };
    let expected_addr = expected as *const XlogDeviceRuntime as usize;

    let barrier = Arc::new(Barrier::new(8));
    let mut handles = Vec::new();
    for _ in 0..8 {
        let barrier = Arc::clone(&barrier);
        handles.push(thread::spawn(move || {
            barrier.wait();
            let rt = XlogDeviceRuntime::try_get(0).expect("runtime");
            rt as *const XlogDeviceRuntime as usize
        }));
    }

    for handle in handles {
        assert_eq!(handle.join().expect("thread panicked"), expected_addr);
    }
}

#[test]
fn runtime_allocates_and_deallocates_through_default_resource() {
    let Some(runtime) = runtime_or_skip() else {
        return;
    };

    let before = runtime.bytes_outstanding();
    let block = runtime
        .allocate(1024, StreamId::DEFAULT, AllocTag("runtime-singleton-test"))
        .expect("allocate through runtime");

    assert_eq!(block.device_ordinal, 0);
    assert_eq!(block.bytes, 1024);
    assert_eq!(runtime.bytes_outstanding(), before + 1024);

    runtime
        .deallocate(block)
        .expect("deallocate through runtime");
    assert_eq!(runtime.bytes_outstanding(), before);
}