/* * Copyright 2002-2017 the original author or authors. * * Licensed 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.springframework.amqp.rabbit.listener; import java.util.Collection; import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * A mechanism to keep track of active objects. * @param <T> the object type. * @author Dave Syer * */ public class ActiveObjectCounter<T> { private final ConcurrentMap<T, CountDownLatch> locks = new ConcurrentHashMap<T, CountDownLatch>(); public void add(T object) { CountDownLatch lock = new CountDownLatch(1); this.locks.putIfAbsent(object, lock); } public void release(T object) { CountDownLatch remove = this.locks.remove(object); if (remove != null) { remove.countDown(); } } public boolean await(long timeout, TimeUnit timeUnit) throws InterruptedException { long t0 = System.currentTimeMillis(); long t1 = t0 + TimeUnit.MILLISECONDS.convert(timeout, timeUnit); while (System.currentTimeMillis() <= t1) { if (this.locks.isEmpty()) { return true; } Collection<T> objects = new HashSet<T>(this.locks.keySet()); for (T object : objects) { CountDownLatch lock = this.locks.get(object); if (lock == null) { continue; } t0 = System.currentTimeMillis(); if (lock.await(t1 - t0, TimeUnit.MILLISECONDS)) { this.locks.remove(object); } } } return false; } public int getCount() { return this.locks.size(); } public void reset() { this.locks.clear(); } }