001/*
002 * JDrupes Builder
003 * Copyright (C) 2026 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.builder.core;
020
021/// An AwaitableCounter.
022///
023@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel")
024public class AwaitableCounter {
025    private int count;
026
027    /// Initializes a new awaitable counter.
028    ///
029    public AwaitableCounter() {
030        // Make javadoc happy
031    }
032
033    /// Increment.
034    ///
035    /// @return the awaitable counter
036    ///
037    public synchronized AwaitableCounter increment() {
038        count++;
039        return this;
040    }
041
042    /// Decrement.
043    ///
044    /// @return the awaitable counter
045    ///
046    public synchronized AwaitableCounter decrement() {
047        count--;
048        if (count == 0) {
049            notifyAll();
050        }
051        return this;
052    }
053
054    /// Create a count.
055    ///
056    /// @return the count
057    ///
058    public Count count() {
059        return new Count();
060    }
061
062    /// Await zero.
063    ///
064    /// @param wanted the wanted
065    /// @return the awaitable counter
066    /// @throws InterruptedException the interrupted exception
067    ///
068    public synchronized AwaitableCounter await(int wanted)
069            throws InterruptedException {
070        while (count != wanted) {
071            wait();
072        }
073        return this;
074    }
075
076    /// Increment/decrement with an AutoCloseable.
077    ///
078    public class Count implements AutoCloseable {
079
080        /// Initializes a new count.
081        ///
082        @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
083        public Count() {
084            increment();
085        }
086
087        /// Close.
088        ///
089        @Override
090        public void close() {
091            decrement();
092        }
093    }
094}