use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
pub struct MemoryTracker {
current_usage: Arc<AtomicU64>,
max_usage: u64,
}
impl MemoryTracker {
pub fn new(max_mb: u32) -> Self {
Self {
current_usage: Arc::new(AtomicU64::new(0)),
max_usage: max_mb as u64 * 1024 * 1024,
}
}
pub fn can_allocate(&self, bytes: u64) -> bool {
self.current_usage.load(Ordering::Relaxed) + bytes <= self.max_usage
}
pub fn allocate(&self, bytes: u64) -> bool {
if self.can_allocate(bytes) {
self.current_usage.fetch_add(bytes, Ordering::Relaxed);
true
} else {
false
}
}
pub fn deallocate(&self, bytes: u64) {
self.current_usage.fetch_sub(bytes, Ordering::Relaxed);
}
pub fn current_bytes(&self) -> u64 {
self.current_usage.load(Ordering::Relaxed)
}
pub fn current_mb(&self) -> f64 {
self.current_bytes() as f64 / (1024.0 * 1024.0)
}
pub fn max_mb(&self) -> u64 {
self.max_usage / (1024 * 1024)
}
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
}
pub fn is_critical(&self) -> bool {
self.usage_percent() > 90.0
}
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)
}
}
pub struct ConcurrencyLimiter {
current: Arc<AtomicU64>,
max: u64,
}
impl ConcurrencyLimiter {
pub fn new(max: u32) -> Self {
Self {
current: Arc::new(AtomicU64::new(0)),
max: max as u64,
}
}
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,
}
}
}
pub fn release(&self) {
self.current.fetch_sub(1, Ordering::Relaxed);
}
pub fn current(&self) -> u64 {
self.current.load(Ordering::Relaxed)
}
pub fn max(&self) -> u64 {
self.max
}
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)
}
}