Record permit draws against a fixed budget and report whether demand was capped.

bounded budget A coordination report can record draws against a bounded budget. A `SemaphoreSlim` created with a fixed capacity grants permits while they last, and `Wait(0)` returns false once the budget is spent, so over-demand is denied rather than blocked. When demand stays under capacity the budget keeps spare permits, when demand exactly matches capacity the budget is spent, and when demand exceeds capacity the extra draws are denied and capped. The status line summarizes whether the budget stayed spare, was spent, or capped demand.

Semaphore Budget Coordination Report

requests
SemaphoreBudgetCoordinationReport.cs
Replay: real traced execution (multi-file project)
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        int requests = 2;
        int capacity = 2;
        var permits = new SemaphoreSlim(capacity, capacity);
        int granted = 0;
        int denied = 0;

        for (int i = 0; i < requests; i++)
        {
            if (permits.Wait(0))
            {
                granted++;
            }
            else
            {
                denied++;
            }
        }

        string status;
        if (denied > 0)
        {
            status = "capped";
        }
        else if (granted == capacity)
        {
            status = "spent";
        }
        else
        {
            status = "spare";
        }

        Console.WriteLine("requests=" + requests + " granted=" + granted + " denied=" + denied + " " + status);
    }
}
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        int requests = 1;
        int capacity = 2;
        var permits = new SemaphoreSlim(capacity, capacity);
        int granted = 0;
        int denied = 0;

        for (int i = 0; i < requests; i++)
        {
            if (permits.Wait(0))
            {
                granted++;
            }
            else
            {
                denied++;
            }
        }

        string status;
        if (denied > 0)
        {
            status = "capped";
        }
        else if (granted == capacity)
        {
            status = "spent";
        }
        else
        {
            status = "spare";
        }

        Console.WriteLine("requests=" + requests + " granted=" + granted + " denied=" + denied + " " + status);
    }
}
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        int requests = 3;
        int capacity = 2;
        var permits = new SemaphoreSlim(capacity, capacity);
        int granted = 0;
        int denied = 0;

        for (int i = 0; i < requests; i++)
        {
            if (permits.Wait(0))
            {
                granted++;
            }
            else
            {
                denied++;
            }
        }

        string status;
        if (denied > 0)
        {
            status = "capped";
        }
        else if (granted == capacity)
        {
            status = "spent";
        }
        else
        {
            status = "spare";
        }

        Console.WriteLine("requests=" + requests + " granted=" + granted + " denied=" + denied + " " + status);
    }
}
  1. requests ← 2, capacity ← 2, permits ← System.Threading.SemaphoreSlim

    5{6    static void Main()7    {8        int requests→ 2 = 2; //@requests=1, 39        int capacity→ 2 = 2;10        var permits→ System.Threading.SemaphoreSlim = new SemaphoreSlim(capacity, capacity);11        int granted→ 0 = 0;12        int denied→ 0 = 0;
  2. for (int i = 0; i < requests; i++)

    pass 1 of 2
    14for (int i0 = 0; i < requests2; i++)15{16    if (permits.Wait(0))
  3. granted ← 1

    pass 1 of 2
    15{16    if (permitsSystem.Threading.SemaphoreSlim.Wait(0))17    {18        granted→ 1++;19    }
  4. for (int i = 0; i < requests; i++)

    pass 2 of 2
    14for (int i1 = 0; i < requests2; i++)15{16    if (permits.Wait(0))
  5. granted ← 2

    pass 2 of 2
    15{16    if (permitsSystem.Threading.SemaphoreSlim.Wait(0))17    {18        granted→ 2++;19    }
  6. string status;

    26string status;27if (denied > 0)
  7. status ← spent

    30}31else if (granted2 == capacity2)32{33    status→ spent = "spent";34}
  8. Console.WriteLine("requests=" + requests + " granted=" + granted + " d…

    40    Console.WriteLine("requests=" + requests2 + " granted=" + granted2 + " denied=" + denied0 + " " + statusspent);41}
    outputrequests=2 granted=2 denied=0 spent
  1. requests ← 1, capacity ← 2, permits ← System.Threading.SemaphoreSlim

    5{6    static void Main()7    {8        int requests→ 1 = 1;9        int capacity→ 2 = 2;10        var permits→ System.Threading.SemaphoreSlim = new SemaphoreSlim(capacity, capacity);11        int granted→ 0 = 0;12        int denied→ 0 = 0;
  2. for (int i = 0; i < requests; i++)

    14for (int i0 = 0; i < requests1; i++)15{16    if (permits.Wait(0))
  3. granted ← 1

    15{16    if (permitsSystem.Threading.SemaphoreSlim.Wait(0))17    {18        granted→ 1++;19    }
  4. string status;

    26string status;27if (denied > 0)
  5. status ← spare

    34}35else36{37    status→ spare = "spare";38}
  6. Console.WriteLine("requests=" + requests + " granted=" + granted + " d…

    40    Console.WriteLine("requests=" + requests1 + " granted=" + granted1 + " denied=" + denied0 + " " + statusspare);41}
    outputrequests=1 granted=1 denied=0 spare
  1. requests ← 3, capacity ← 2, permits ← System.Threading.SemaphoreSlim

    5{6    static void Main()7    {8        int requests→ 3 = 3;9        int capacity→ 2 = 2;10        var permits→ System.Threading.SemaphoreSlim = new SemaphoreSlim(capacity, capacity);11        int granted→ 0 = 0;12        int denied→ 0 = 0;
  2. for (int i = 0; i < requests; i++)

    pass 1 of 3
    14for (int i0 = 0; i < requests3; i++)15{16    if (permits.Wait(0))
    All 3 passes — pass 1 is the card above
    passipermitsgranteddenied
    10System.Threading.SemaphoreSlim0 1
    21System.Threading.SemaphoreSlim1 2
    320 1
  3. granted ← 1

    pass 1 of 2
    15{16    if (permitsSystem.Threading.SemaphoreSlim.Wait(0))17    {18        granted→ 1++;19    }
  4. granted ← 2

    pass 2 of 2
    15{16    if (permitsSystem.Threading.SemaphoreSlim.Wait(0))17    {18        granted→ 2++;19    }
  5. denied ← 1

    19}20else21{22    denied→ 1++;23}
  6. string status;

    26string status;27if (denied > 0)
  7. status ← capped

    26string status;27if (denied1 > 0)28{29    status→ capped = "capped";30}
  8. Console.WriteLine("requests=" + requests + " granted=" + granted + " d…

    40    Console.WriteLine("requests=" + requests3 + " granted=" + granted2 + " denied=" + denied1 + " " + statuscapped);41}
    outputrequests=3 granted=2 denied=1 capped