rsclaw 0.0.1-alpha.1

rsclaw: High-performance AI agent (BETA). Optimized for M4 Max and 2GB VPS. 100% compatible with openclaw
Documentation
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;

/// Memory usage tracker.
pub struct MemoryTracker {
    current_usage: Arc<AtomicU64>,
    max_usage: u64,
}

impl MemoryTracker {
    /// Create a new memory tracker.
    pub fn new(max_mb: u32) -> Self {
        Self {
            current_usage: Arc::new(AtomicU64::new(0)),
            max_usage: max_mb as u64 * 1024 * 1024,
        }
    }

    /// Check if allocation is allowed.
    pub fn can_allocate(&self, bytes: u64) -> bool {
        self.current_usage.load(Ordering::Relaxed) + bytes <= self.max_usage
    }

    /// Track allocation.
    pub fn allocate(&self, bytes: u64) -> bool {
        if self.can_allocate(bytes) {
            self.current_usage.fetch_add(bytes, Ordering::Relaxed);
            true
        } else {
            false
        }
    }

    /// Track deallocation.
    pub fn deallocate(&self, bytes: u64) {
        self.current_usage.fetch_sub(bytes, Ordering::Relaxed);
    }

    /// Get current usage in bytes.
    pub fn current_bytes(&self) -> u64 {
        self.current_usage.load(Ordering::Relaxed)
    }

    /// Get current usage in MB.
    pub fn current_mb(&self) -> f64 {
        self.current_bytes() as f64 / (1024.0 * 1024.0)
    }

    /// Get max usage in MB.
    pub fn max_mb(&self) -> u64 {
        self.max_usage / (1024 * 1024)
    }

    /// Get usage percentage.
    pub fn usage_percent(&self) -> f64 {
        if self.max_usage == 0 {
            return 0.0;
        }
        (self.current_bytes() as f64 / self.max_usage as f64) * 100.0
    }

    /// Check if memory is critically low.
    pub fn is_critical(&self) -> bool {
        self.usage_percent() > 90.0
    }

    /// Reset usage counter.
    pub fn reset(&self) {
        self.current_usage.store(0, Ordering::Relaxed);
    }
}

impl Clone for MemoryTracker {
    fn clone(&self) -> Self {
        Self {
            current_usage: self.current_usage.clone(),
            max_usage: self.max_usage,
        }
    }
}

impl Default for MemoryTracker {
    fn default() -> Self {
        Self::new(512)
    }
}

/// Concurrency limiter for agents.
pub struct ConcurrencyLimiter {
    current: Arc<AtomicU64>,
    max: u64,
}

impl ConcurrencyLimiter {
    /// Create a new concurrency limiter.
    pub fn new(max: u32) -> Self {
        Self {
            current: Arc::new(AtomicU64::new(0)),
            max: max as u64,
        }
    }

    /// Try to acquire a slot.
    pub fn try_acquire(&self) -> bool {
        let mut current = self.current.load(Ordering::Relaxed);
        loop {
            if current >= self.max {
                return false;
            }
            match self.current.compare_exchange_weak(
                current,
                current + 1,
                Ordering::Relaxed,
                Ordering::Relaxed,
            ) {
                Ok(_) => return true,
                Err(new) => current = new,
            }
        }
    }

    /// Release a slot.
    pub fn release(&self) {
        self.current.fetch_sub(1, Ordering::Relaxed);
    }

    /// Get current count.
    pub fn current(&self) -> u64 {
        self.current.load(Ordering::Relaxed)
    }

    /// Get max count.
    pub fn max(&self) -> u64 {
        self.max
    }

    /// Check if at capacity.
    pub fn is_at_capacity(&self) -> bool {
        self.current() >= self.max
    }
}

impl Clone for ConcurrencyLimiter {
    fn clone(&self) -> Self {
        Self {
            current: self.current.clone(),
            max: self.max,
        }
    }
}

impl Default for ConcurrencyLimiter {
    fn default() -> Self {
        Self::new(3)
    }
}