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/// A counter that supports waiting for a specific value. The waiting 022/// thread is woken when the counter hits the target value. 023/// 024@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel") 025public class AwaitableCounter { 026 private int count; 027 028 /// Initializes a new awaitable counter. 029 /// 030 public AwaitableCounter() { 031 // Make javadoc happy 032 } 033 034 /// Increment the count's value. 035 /// 036 /// @return the counter 037 /// 038 public synchronized AwaitableCounter increment() { 039 count++; 040 return this; 041 } 042 043 /// Decrement the counter's value. 044 /// 045 /// @return the counter 046 /// 047 public synchronized AwaitableCounter decrement() { 048 count--; 049 if (count == 0) { 050 notifyAll(); 051 } 052 return this; 053 } 054 055 /// Return the counter's value. 056 /// 057 /// @return the value 058 /// 059 public int value() { 060 return count; 061 } 062 063 /// Create an increment. 064 /// 065 /// @return the count 066 /// 067 public Increment acquire() { 068 return new Increment(); 069 } 070 071 /// Wait for the counter to reach the given value. 072 /// 073 /// @param wanted the wanted 074 /// @return the counter 075 /// @throws InterruptedException the interrupted exception 076 /// 077 public synchronized AwaitableCounter await(int wanted) 078 throws InterruptedException { 079 while (count != wanted) { 080 wait(); 081 } 082 return this; 083 } 084 085 /// Increment/decrement with an AutoCloseable. This supports 086 /// reliable increment/decrement using try-with-resources. 087 /// 088 public class Increment implements AutoCloseable { 089 090 /// Initializes a new Increment. Increments the counter. 091 /// 092 @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") 093 public Increment() { 094 increment(); 095 } 096 097 /// Decrements the counter. 098 /// 099 @Override 100 public void close() { 101 decrement(); 102 } 103 } 104}