Count arrivals down to a release barrier and report whether it has opened.

countdown to release A countdown barrier opens only after a fixed number of parties arrive. A `std::atomic<int>` remaining counter starts at the party count, and each arrival uses `fetch_sub` to drop it by one while it is still positive, so the counter never goes below zero and the number of recorded signals is exact. The single deterministic pass means the report can state how many arrivals were signaled and how many remain, labeling the barrier waiting before the first arrival, partial while some parties are missing, or released once the count reaches zero.

Countdown Barrier Coordination Report

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

int main() {
    int arrivals = 2;
    const int parties = 3;
    std::atomic<int> remaining{parties};
    int signaled = 0;

    for (int i = 0; i < arrivals; ++i) {
        if (remaining.load() > 0) {
            remaining.fetch_sub(1);
            signaled += 1;
        }
    }

    int left = remaining.load();

    std::string status;
    if (signaled == 0) {
        status = "waiting";
    } else if (left > 0) {
        status = "partial";
    } else {
        status = "released";
    }

    std::cout << "arrivals=" << arrivals
              << " signaled=" << signaled
              << " remaining=" << left
              << " " << status << std::endl;
    return 0;
}
#include <atomic>
#include <iostream>
#include <string>

int main() {
    int arrivals = 0;
    const int parties = 3;
    std::atomic<int> remaining{parties};
    int signaled = 0;

    for (int i = 0; i < arrivals; ++i) {
        if (remaining.load() > 0) {
            remaining.fetch_sub(1);
            signaled += 1;
        }
    }

    int left = remaining.load();

    std::string status;
    if (signaled == 0) {
        status = "waiting";
    } else if (left > 0) {
        status = "partial";
    } else {
        status = "released";
    }

    std::cout << "arrivals=" << arrivals
              << " signaled=" << signaled
              << " remaining=" << left
              << " " << status << std::endl;
    return 0;
}
#include <atomic>
#include <iostream>
#include <string>

int main() {
    int arrivals = 3;
    const int parties = 3;
    std::atomic<int> remaining{parties};
    int signaled = 0;

    for (int i = 0; i < arrivals; ++i) {
        if (remaining.load() > 0) {
            remaining.fetch_sub(1);
            signaled += 1;
        }
    }

    int left = remaining.load();

    std::string status;
    if (signaled == 0) {
        status = "waiting";
    } else if (left > 0) {
        status = "partial";
    } else {
        status = "released";
    }

    std::cout << "arrivals=" << arrivals
              << " signaled=" << signaled
              << " remaining=" << left
              << " " << status << std::endl;
    return 0;
}
  1. arrivals ← 2, parties ← 3, remaining ← 3, signaled ← 0

    5int main() {6    int arrivals→ 2 = 2; //@arrivals=0, 37    const int parties→ 3 = 3;8    std::atomic<int> remaining→ 3{parties3};9    int signaled→ 0 = 0;
  2. for (int i = 0; i < arrivals; ++i)

    pass 1 of 2
    11for (int i0 = 0; i < arrivals2; ++i) {12    if (remaining.load() > 0) {
  3. remaining ← 2, signaled ← 1

    pass 1 of 2
    11for (int i = 0; i < arrivals; ++i) {12    if (remaining3.load() > 0) {13        remaining→ 2.fetch_sub(1);14        signaled→ 1 += 1;15    }
  4. for (int i = 0; i < arrivals; ++i)

    pass 2 of 2
    11for (int i1 = 0; i < arrivals2; ++i) {12    if (remaining.load() > 0) {
  5. remaining ← 1, signaled ← 2

    pass 2 of 2
    11for (int i = 0; i < arrivals; ++i) {12    if (remaining2.load() > 0) {13        remaining→ 1.fetch_sub(1);14        signaled→ 2 += 1;15    }
  6. left ← 1, status ← (empty)

    18int left→ 1 = remaining1.load();1920std::string status→ (empty);21if (signaled == 0) {
  7. status ← partial

    22    status = "waiting";23} else if (left1 > 0) {24    status→ partial = "partial";25} else {
  8. std::cout << "arrivals=" << arrivals

    29    std::cout << "arrivals=" << arrivals230              << " signaled=" << signaled231              << " remaining=" << left132              << " " << statuspartial << std::endl;33    return 0;34}
    outputarrivals=2 signaled=2 remaining=1 partial
  1. arrivals ← 0, parties ← 3, remaining ← 3, signaled ← 0, left ← 3

    5int main() {6    int arrivals→ 0 = 0;7    const int parties→ 3 = 3;8    std::atomic<int> remaining→ 3{parties3};9    int signaled→ 0 = 0;1011    for (int i = 0; i < arrivals; ++i) {12        if (remaining.load() > 0) {13            remaining.fetch_sub(1);14            signaled += 1;15        }16    }1718    int left→ 3 = remaining3.load();1920    std::string status→ (empty);21    if (signaled == 0) {
  2. status ← waiting

    20std::string status;21if (signaled0 == 0) {22    status→ waiting = "waiting";23} else if (left > 0) {
  3. std::cout << "arrivals=" << arrivals

    29    std::cout << "arrivals=" << arrivals030              << " signaled=" << signaled031              << " remaining=" << left332              << " " << statuswaiting << std::endl;33    return 0;34}
    outputarrivals=0 signaled=0 remaining=3 waiting
  1. arrivals ← 3, parties ← 3, remaining ← 3, signaled ← 0

    5int main() {6    int arrivals→ 3 = 3;7    const int parties→ 3 = 3;8    std::atomic<int> remaining→ 3{parties3};9    int signaled→ 0 = 0;
  2. for (int i = 0; i < arrivals; ++i)

    pass 1 of 3
    11for (int i0 = 0; i < arrivals3; ++i) {12    if (remaining.load() > 0) {
    All 3 passes — pass 1 is the card above
    passi
    10
    21
    32
  3. remaining ← 2, signaled ← 1

    pass 1 of 3
    11for (int i = 0; i < arrivals; ++i) {12    if (remaining3.load() > 0) {13        remaining→ 2.fetch_sub(1);14        signaled→ 1 += 1;15    }
    All 3 passes — pass 1 is the card above
    passremainingsignaled
    13 20 1
    22 11 2
    31 02 3
  4. left ← 0, status ← (empty)

    18int left→ 0 = remaining0.load();1920std::string status→ (empty);21if (signaled == 0) {
  5. status ← released

    24    status = "partial";25} else {26    status→ released = "released";27}
  6. std::cout << "arrivals=" << arrivals

    29    std::cout << "arrivals=" << arrivals330              << " signaled=" << signaled331              << " remaining=" << left032              << " " << statusreleased << std::endl;33    return 0;34}
    outputarrivals=3 signaled=3 remaining=0 released