<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/**
 * A one-time use barrier (aka latch) that allows threads to wait until a
 * sufficient number of other threads have reached the barrier.  Has the ability
 * to execute a postprocessing action after all threads have reached barrier
 * before opening.
 */
public class Barrier {
    /**
     * Number of threads that must reach barrier until it opens.
     */
    private final int totalThreads;

    /**
     * Number of threads that have reached barrier.  Guarded by `lock`.
     */
    private int awaitingThreads;

    /**
     * Function to run on last awaiting thread before opening barrier.  May only
     * be executed once.
     */
    private final Runnable postAction;

    /**
     * Mutex guarding `awaitingThreads` and condition variable for threads to
     * wait on while barrier is closed.
     */
    private Object lock;

    /**
     * Create a new barrier that is closed until `totalThreads` threads have
     * called `await()`.  Once all threads have reached barrier, `postAction`
     * will be run before the threads are released.
     */
    public Barrier(int totalThreads, Runnable postAction) {
        this.totalThreads = totalThreads;
        awaitingThreads = 0;
        this.postAction = postAction;
        lock = new Object();
    }

    /**
     * Return the total number of threads that must reach this barrier before
     * it will open.
     */
    public int totalThreads() {
        // TODO: Should anything be changed to avoid race conditions here?
        return totalThreads;
    }

    /**
     * Return the number of threads that have reached this barrier.
     */
    public int awaitingThreads() {
        // TODO: Should anything be changed to avoid race conditions here?
        synchronized (lock) {
            return awaitingThreads;
        }
    }

    /**
     * Block until `totalThreads` threads have invoked `await()` on this
     * barrier.  If the calling thread is the last expected thread, it will
     * execute `postAction` before all threads are unblocked.
     */
    public void await() throws InterruptedException {
        // TODO: Implement this method according to its specifications.

//        awaitingThreads += 1;
//        if (awaitingThreads == totalThreads) {
//            postAction.run();
//        }
//        while (awaitingThreads &lt; totalThreads) { /* spin */ }

        synchronized (lock) {
            awaitingThreads += 1;
            if (awaitingThreads == totalThreads) {
                postAction.run();
                lock.notifyAll();
            } else {
                while (awaitingThreads &lt; totalThreads) {
                    lock.wait();
                }
            }
        }
    }
}
</pre></body></html>