| /******************************************************************************* |
| * Copyright (c) 2005, 2014 Cognos Incorporated, IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Cognos Incorporated - initial API and implementation |
| * IBM Corporation - bug fixes and enhancements |
| * Raymond Augé <raymond.auge@liferay.com> - Bug 436698 |
| *******************************************************************************/ |
| package org.eclipse.equinox.http.servlet.internal.registration; |
| |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.concurrent.locks.Condition; |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReadWriteLock; |
| import java.util.concurrent.locks.ReentrantReadWriteLock; |
| import org.osgi.dto.DTO; |
| |
| public abstract class Registration<T, D extends DTO> { |
| |
| private final D d; |
| private final T t; |
| |
| protected final AtomicInteger referenceCount = new AtomicInteger(); |
| |
| public Registration(T t, D d) { |
| this.t = t; |
| this.d = d; |
| } |
| |
| public void addReference() { |
| readLock.lock(); |
| |
| try { |
| referenceCount.incrementAndGet(); |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| public void removeReference() { |
| readLock.lock(); |
| |
| try { |
| if (referenceCount.decrementAndGet() == 0 && destroyed) { |
| readLock.unlock(); |
| |
| writeLock.lock(); |
| |
| try { |
| condition.signalAll(); |
| } |
| finally { |
| writeLock.unlock(); |
| |
| readLock.lock(); |
| } |
| } |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| public void destroy() { |
| boolean interrupted = false; |
| |
| writeLock.lock(); |
| |
| destroyed = true; |
| |
| try { |
| while (referenceCount.get() != 0) { |
| try { |
| condition.await(); |
| } |
| catch (InterruptedException ie) { |
| interrupted = true; |
| } |
| } |
| } |
| finally { |
| writeLock.unlock(); |
| |
| if (interrupted) { |
| Thread.currentThread().interrupt(); |
| } |
| } |
| } |
| |
| private volatile boolean destroyed; |
| |
| private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); |
| |
| private final Lock readLock = readWriteLock.readLock(); |
| private final Lock writeLock = readWriteLock.writeLock(); |
| private final Condition condition = writeLock.newCondition(); |
| |
| public D getD() { |
| return d; |
| } |
| |
| public T getT() { |
| return t; |
| } |
| |
| @Override |
| public String toString() { |
| return getD().toString(); |
| } |
| |
| } |