memkit-async 0.2.0-beta.1

Async-aware memory allocators for memkit
use memkit_async::{MkAsyncPool, MkBackpressure};
use std::time::Duration;
use std::sync::Arc;
use tokio::time::sleep;

#[tokio::test]
async fn test_pool_contention() {
    // Create a small pool
    let pool = MkAsyncPool::new(2, MkBackpressure::Wait);
    
    // Add items
    pool.add(10).unwrap();
    pool.add(20).unwrap();
    
    // We will spawn 10 tasks competing for 2 items
    let mut handles = Vec::new();
    let counter = Arc::new(std::sync::atomic::AtomicUsize::new(0));
    
    for i in 0..10 {
        let pool = pool.clone();
        let counter = counter.clone();
        
        handles.push(tokio::spawn(async move {
            // Acquire from pool (should wait if empty)
            let guard = pool.acquire().await.expect("Failed to acquire");
            
            // Hold it for a bit
            sleep(Duration::from_millis(10)).await;
            
            // Check value
            let val = *guard;
            assert!(val == 10 || val == 20);
            
            counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
            
            println!("Task {} acquired {}", i, val);
            // Drop guard returns item to pool
        }));
    }
    
    // Wait for all
    for h in handles {
        h.await.unwrap();
    }
    
    // Check all tasks succeeded
    assert_eq!(counter.load(std::sync::atomic::Ordering::Relaxed), 10);
    assert_eq!(pool.available(), 2);
}

#[tokio::test]
async fn test_backpressure_timeout() {
    let pool = MkAsyncPool::new(1, MkBackpressure::Timeout(Duration::from_millis(100)));
    pool.add(1).unwrap();
    
    // Acquire the only item
    let _guard1 = pool.acquire().await.unwrap();
    
    // Try to acquire another (should timeout)
    let result = pool.acquire().await;
    assert!(result.is_none(), "Should have timed out");
}