/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openejb.util; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; /** * @version $Rev$ $Date$ */ public class CountingLatch { private final Sync sync; public CountingLatch() { this(0); } public CountingLatch(final int count) { this.sync = new Sync(count); } public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public boolean await(final long timeout, final TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } public void countDown() { sync.releaseShared(-1); } public void countUp() { sync.releaseShared(1); } public long getCount() { return sync.getCount(); } private static final class Sync extends AbstractQueuedSynchronizer { private Sync(final int count) { setState(count); } public boolean tryReleaseShared(final int releases) { while (true) { final int count = getState(); final int next = count + releases; if (next < 0) { return false; } if (compareAndSetState(count, next)) { return next == 0; } } } public int tryAcquireShared(final int acquires) { return getState() == 0 ? 1 : -1; } int getCount() { return getState(); } } }