Draw against a fixed budget and report whether any request was capped.

bounded draw A fixed budget admits only as many draws as it holds. A `std::atomic<int>` budget starts at the capacity, and each request reads the current value and uses `compare_exchange_weak` to drop it by one while it is still positive, retrying on a spurious miss but never blocking. A request that finds the budget at zero is denied instead. The single deterministic pass lets the report count granted versus denied draws and label the section spare when capacity is left, spent when it lands exactly on zero, or capped when a request was denied.

Atomic Budget Coordination Report

requests
atomic_budget_coordination_report.cpp
Replay: real traced execution (multi-file project)
#include <atomic>
#include <iostream>
#include <string>

int main() {
    int requests = 2;
    const int capacity = 2;
    std::atomic<int> budget{capacity};
    int granted = 0;
    int denied = 0;

    for (int i = 0; i < requests; ++i) {
        int current = budget.load();
        bool drawn = false;
        while (current > 0) {
            if (budget.compare_exchange_weak(current, current - 1)) {
                drawn = true;
                break;
            }
        }
        if (drawn) {
            granted += 1;
        } else {
            denied += 1;
        }
    }

    int spare = budget.load();

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

    std::cout << "requests=" << requests
              << " granted=" << granted
              << " denied=" << denied
              << " " << status << std::endl;
    return 0;
}
#include <atomic>
#include <iostream>
#include <string>

int main() {
    int requests = 1;
    const int capacity = 2;
    std::atomic<int> budget{capacity};
    int granted = 0;
    int denied = 0;

    for (int i = 0; i < requests; ++i) {
        int current = budget.load();
        bool drawn = false;
        while (current > 0) {
            if (budget.compare_exchange_weak(current, current - 1)) {
                drawn = true;
                break;
            }
        }
        if (drawn) {
            granted += 1;
        } else {
            denied += 1;
        }
    }

    int spare = budget.load();

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

    std::cout << "requests=" << requests
              << " granted=" << granted
              << " denied=" << denied
              << " " << status << std::endl;
    return 0;
}
#include <atomic>
#include <iostream>
#include <string>

int main() {
    int requests = 3;
    const int capacity = 2;
    std::atomic<int> budget{capacity};
    int granted = 0;
    int denied = 0;

    for (int i = 0; i < requests; ++i) {
        int current = budget.load();
        bool drawn = false;
        while (current > 0) {
            if (budget.compare_exchange_weak(current, current - 1)) {
                drawn = true;
                break;
            }
        }
        if (drawn) {
            granted += 1;
        } else {
            denied += 1;
        }
    }

    int spare = budget.load();

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

    std::cout << "requests=" << requests
              << " granted=" << granted
              << " denied=" << denied
              << " " << status << std::endl;
    return 0;
}
  1. requests ← 2, capacity ← 2, budget ← 2, granted ← 0, denied ← 0

    5int main() {6    int requests→ 2 = 2; //@requests=1, 37    const int capacity→ 2 = 2;8    std::atomic<int> budget→ 2{capacity2};9    int granted→ 0 = 0;10    int denied→ 0 = 0;
  2. current ← 2, drawn ← 0

    pass 1 of 2
    12for (int i0 = 0; i < requests2; ++i) {13    int current→ 2 = budget2.load();14    bool drawn→ 0 = false;15    while (current > 0) {
  3. while (current > 0)

    pass 1 of 2
    14bool drawn = false;15while (current2 > 0) {16    if (budget.compare_exchange_weak(current, current - 1)) {
  4. drawn ← 1

    pass 1 of 2
    15while (current > 0) {16    if (budget1.compare_exchange_weak(current2, current - 1)) {17        drawn→ 1 = true;18        break;19    }
  5. granted ← 1

    pass 1 of 2
    20}21if (drawn1) {22    granted→ 1 += 1;23} else {
  6. current ← 1, drawn ← 0

    pass 2 of 2
    12for (int i1 = 0; i < requests2; ++i) {13    int current→ 1 = budget1.load();14    bool drawn→ 0 = false;15    while (current > 0) {
  7. while (current > 0)

    pass 2 of 2
    14bool drawn = false;15while (current1 > 0) {16    if (budget.compare_exchange_weak(current, current - 1)) {
  8. drawn ← 1

    pass 2 of 2
    15while (current > 0) {16    if (budget0.compare_exchange_weak(current1, current - 1)) {17        drawn→ 1 = true;18        break;19    }
  9. granted ← 2

    pass 2 of 2
    20}21if (drawn1) {22    granted→ 2 += 1;23} else {
  10. spare ← 0, status ← (empty)

    28int spare→ 0 = budget0.load();2930std::string status→ (empty);31if (denied > 0) {
  11. status ← spent

    34    status = "spare";35} else {36    status→ spent = "spent";37}
  12. std::cout << "requests=" << requests

    39    std::cout << "requests=" << requests240              << " granted=" << granted241              << " denied=" << denied042              << " " << statusspent << std::endl;43    return 0;44}
    outputrequests=2 granted=2 denied=0 spent
  1. requests ← 1, capacity ← 2, budget ← 2, granted ← 0, denied ← 0

    5int main() {6    int requests→ 1 = 1;7    const int capacity→ 2 = 2;8    std::atomic<int> budget→ 2{capacity2};9    int granted→ 0 = 0;10    int denied→ 0 = 0;
  2. current ← 2, drawn ← 0

    12for (int i0 = 0; i < requests1; ++i) {13    int current→ 2 = budget2.load();14    bool drawn→ 0 = false;15    while (current > 0) {
  3. while (current > 0)

    14bool drawn = false;15while (current2 > 0) {16    if (budget.compare_exchange_weak(current, current - 1)) {
  4. drawn ← 1

    15while (current > 0) {16    if (budget1.compare_exchange_weak(current2, current - 1)) {17        drawn→ 1 = true;18        break;19    }
  5. granted ← 1

    20}21if (drawn1) {22    granted→ 1 += 1;23} else {
  6. spare ← 1, status ← (empty)

    28int spare→ 1 = budget1.load();2930std::string status→ (empty);31if (denied > 0) {
  7. status ← spare

    32    status = "capped";33} else if (spare1 > 0) {34    status→ spare = "spare";35} else {
  8. std::cout << "requests=" << requests

    39    std::cout << "requests=" << requests140              << " granted=" << granted141              << " denied=" << denied042              << " " << statusspare << std::endl;43    return 0;44}
    outputrequests=1 granted=1 denied=0 spare
  1. requests ← 3, capacity ← 2, budget ← 2, granted ← 0, denied ← 0

    5int main() {6    int requests→ 3 = 3;7    const int capacity→ 2 = 2;8    std::atomic<int> budget→ 2{capacity2};9    int granted→ 0 = 0;10    int denied→ 0 = 0;
  2. current ← 2, drawn ← 0

    pass 1 of 3
    12for (int i0 = 0; i < requests3; ++i) {13    int current→ 2 = budget2.load();14    bool drawn→ 0 = false;15    while (current > 0) {
    All 3 passes — pass 1 is the card above
    passibudgetcurrentdrawngranteddenied
    102200 1
    211101 2
    320000 1
  3. while (current > 0)

    pass 1 of 2
    14bool drawn = false;15while (current2 > 0) {16    if (budget.compare_exchange_weak(current, current - 1)) {
  4. drawn ← 1

    pass 1 of 2
    15while (current > 0) {16    if (budget1.compare_exchange_weak(current2, current - 1)) {17        drawn→ 1 = true;18        break;19    }
  5. granted ← 1

    pass 1 of 2
    20}21if (drawn1) {22    granted→ 1 += 1;23} else {
  6. while (current > 0)

    pass 2 of 2
    14bool drawn = false;15while (current1 > 0) {16    if (budget.compare_exchange_weak(current, current - 1)) {
  7. drawn ← 1

    pass 2 of 2
    15while (current > 0) {16    if (budget0.compare_exchange_weak(current1, current - 1)) {17        drawn→ 1 = true;18        break;19    }
  8. granted ← 2

    pass 2 of 2
    20}21if (drawn1) {22    granted→ 2 += 1;23} else {
  9. denied ← 1

    22    granted += 1;23} else {24    denied→ 1 += 1;25}
  10. spare ← 0, status ← (empty)

    28int spare→ 0 = budget0.load();2930std::string status→ (empty);31if (denied > 0) {
  11. status ← capped

    30std::string status;31if (denied1 > 0) {32    status→ capped = "capped";33} else if (spare > 0) {
  12. std::cout << "requests=" << requests

    39    std::cout << "requests=" << requests340              << " granted=" << granted241              << " denied=" << denied142              << " " << statuscapped << std::endl;43    return 0;44}
    outputrequests=3 granted=2 denied=1 capped