pub struct GlobalResourceManager { /* private fields */ }Expand description
Global resource manager for system-wide resource coordination
§Design Pattern: Centralized Resource Governance
This manager prevents resource oversubscription by providing a global pool of CPU and I/O tokens that must be acquired before work begins.
§Educational Notes
Why semaphores?
- Semaphores provide backpressure: work waits when resources are saturated
- RAII permits auto-release resources on drop
- Async-aware: integrates with Tokio runtime
Why separate CPU and I/O tokens?
- CPU work and I/O work have different characteristics
- CPU: Limited by cores, benefits from parallelism = cores
- I/O: Limited by device queue depth, different optimal values
Why memory as gauge only?
- Memory is harder to predict and control
- Start with monitoring, add enforcement later if needed
- Avoids complexity in Phase 1
Implementations§
Source§impl GlobalResourceManager
impl GlobalResourceManager
Sourcepub fn new(config: ResourceConfig) -> Result<Self, PipelineError>
pub fn new(config: ResourceConfig) -> Result<Self, PipelineError>
Creates a new global resource manager with the given configuration
§Educational: Resource Detection and Configuration
This method demonstrates:
- Auto-detection of system resources (CPU cores)
- Device-specific I/O optimization
- Sensible defaults with override capability
§Examples
// Use defaults (auto-detected)
let manager = GlobalResourceManager::new(Default::default())?;
// Custom configuration
let manager = GlobalResourceManager::new(ResourceConfig {
cpu_tokens: Some(6), // Override: use 6 CPU workers
storage_type: StorageType::NVMe,
..Default::default()
})?;Sourcepub async fn acquire_cpu(&self) -> Result<SemaphorePermit<'_>, PipelineError>
pub async fn acquire_cpu(&self) -> Result<SemaphorePermit<'_>, PipelineError>
Acquire a CPU token (explicit style - pedagogical)
§Educational Pattern: Explicit Acquisition
This method shows the explicit pattern where you:
- Call acquire
- Get back a permit
- Permit is held as long as the guard lives
- Permit is auto-released when dropped (RAII)
§Usage
let _cpu_permit = RESOURCE_MANAGER.acquire_cpu().await?;
// Do CPU work
// Permit auto-released here when _cpu_permit goes out of scope§Backpressure
If all CPU tokens are in use, this method waits until one becomes available. This creates natural backpressure and prevents oversubscription.
Sourcepub async fn acquire_io(&self) -> Result<SemaphorePermit<'_>, PipelineError>
pub async fn acquire_io(&self) -> Result<SemaphorePermit<'_>, PipelineError>
Acquire an I/O token
§Educational: Same pattern as CPU tokens
Uses the same semaphore pattern but for I/O operations. Prevents too many concurrent I/O operations from overwhelming the storage device.
§Usage
let _io_permit = RESOURCE_MANAGER.acquire_io().await?;
// Do I/O operation (read/write)
// Permit auto-releasedSourcepub fn allocate_memory(&self, bytes: usize)
pub fn allocate_memory(&self, bytes: usize)
Track memory allocation (gauge only, no enforcement)
§Educational: Simple Atomic Counter
Uses Ordering::Relaxed because:
- We only need atomicity (no torn reads/writes)
- No coordination with other atomic variables needed
- This is just a gauge for monitoring
See atomic_ordering.rs for more on ordering choices.
Sourcepub fn deallocate_memory(&self, bytes: usize)
pub fn deallocate_memory(&self, bytes: usize)
Track memory deallocation
Sourcepub fn memory_used(&self) -> usize
pub fn memory_used(&self) -> usize
Get current memory usage
Sourcepub fn memory_capacity(&self) -> usize
pub fn memory_capacity(&self) -> usize
Get memory capacity
Sourcepub fn cpu_tokens_available(&self) -> usize
pub fn cpu_tokens_available(&self) -> usize
Get number of available CPU tokens
§Educational: Observability
This method provides visibility into resource saturation. If available_permits() is consistently 0, you’re CPU-saturated.
Sourcepub fn cpu_tokens_total(&self) -> usize
pub fn cpu_tokens_total(&self) -> usize
Get total number of CPU tokens
Sourcepub fn io_tokens_available(&self) -> usize
pub fn io_tokens_available(&self) -> usize
Get number of available I/O tokens
Sourcepub fn io_tokens_total(&self) -> usize
pub fn io_tokens_total(&self) -> usize
Get total number of I/O tokens
Auto Trait Implementations§
impl Freeze for GlobalResourceManager
impl !RefUnwindSafe for GlobalResourceManager
impl Send for GlobalResourceManager
impl Sync for GlobalResourceManager
impl Unpin for GlobalResourceManager
impl !UnwindSafe for GlobalResourceManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more