Expand description
orchestrator_lock provides a specialized mutex implementation for scenarios
where fine-grained control over mutex access is required. Unlike a standard
mutex where any code with a reference can attempt to acquire the lock, this
implementation separates the concerns of lock orchestration from lock usage.
§Core Concepts
- 
OrchestratorMutex: The central coordinator that owns the protected value and controls access to it.
 - 
Granter: A capability token that allows the orchestrator to grant lock access to a specific locker.
 - 
MutexLocker: The component that can acquire and use the lock, but only when explicitly granted access by the orchestrator.
 - 
MutexGuard: Provides access to the protected value, similar to a standard mutex guard.
 
§Example
use tokio::time::Duration;
use orchestrator_lock::OrchestratorMutex;
#[tokio::main(flavor = "current_thread")]
async fn main() {
    // Create a shared counter with initial value 0
    let mut orchestrator = OrchestratorMutex::new(0);
     
    // Create two granter/locker pairs
    let (mut granter1, mut locker1) = orchestrator.add_locker();
    let (mut granter2, mut locker2) = orchestrator.add_locker();
     
    // Task 1: Increments by 1 each time
    let task1 = tokio::spawn(async move {
        let expected = [0, 2, 6];
        for i in 0..3 {
            if let Some(mut guard) = locker1.acquire().await {
                assert_eq!(*guard, expected[i]);
                *guard += 1;
                tokio::time::sleep(Duration::from_millis(10)).await;
            }
        }
        locker1
    });
     
    // Task 2: Multiplies by 2 each time
    let task2 = tokio::spawn(async move {
        let expected = [1, 3, 7];
        for i in 0..3 {
            if let Some(mut guard) = locker2.acquire().await {
                assert_eq!(*guard, expected[i]);
                *guard *= 2;
                tokio::time::sleep(Duration::from_millis(10)).await;
            }
        }
        locker2
    });
     
    // Orchestration: Alternate between the two tasks
    for i in 0..3 {
        // Grant access to task 1
        let task1_holding = orchestrator.grant_access(&mut granter1).await.unwrap();
        task1_holding.await;
         
        // Grant access to task 2
        let task2_holding = orchestrator.grant_access(&mut granter2).await.unwrap();
        task2_holding.await;
    }
    assert_eq!(*orchestrator.acquire().await, 14);
    // Clean up
    let _ = task1.await.unwrap();
    let _ = task2.await.unwrap();
}