org.eclipse.osgi.internal.container.LockSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.osgi Show documentation
Show all versions of org.eclipse.osgi Show documentation
This is org.eclipse.osgi jar used by Scout SDK
/*******************************************************************************
* Copyright (c) 2012, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.container;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/*
* Implementation note: This class does not pool ReentrantLocks for the objects
* that are being locked. This means that if the same object is locked and unlocked
* over and over then new ReentrantLocks are created each time. This set should be
* used with care. If the same object is going to be locked/unlocked over and over then
* consider using a different locking strategy.
*
* Previous implementations of this class attempted to use a WeakHashMap to cache
* the locks, but this proved to be a flawed approach because of the unpredictable
* timing of garbage collection, particularly with autoboxed types (e.g. bundle
* long ids).
*/
public class LockSet {
static final class LockHolder {
private final AtomicInteger useCount = new AtomicInteger(0);
private final ReentrantLock lock = new ReentrantLock();
int incrementUseCount() {
return useCount.incrementAndGet();
}
int decremementUseCount() {
return useCount.decrementAndGet();
}
boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return !lock.isHeldByCurrentThread() && lock.tryLock(time, unit);
}
void unlock() {
lock.unlock();
}
}
private final Map locks = new HashMap();
public boolean tryLock(T t, long time, TimeUnit unit) throws InterruptedException {
final boolean previousInterruption = Thread.interrupted();
try {
LockHolder lock;
synchronized (locks) {
lock = locks.get(t);
if (lock == null) {
lock = new LockHolder();
locks.put(t, lock);
}
lock.incrementUseCount();
}
// all interested threads have the lock object and the use count is the number of such threads
boolean acquired = false;
try {
acquired = lock.tryLock(time, unit);
return acquired;
} finally {
if (!acquired) {
synchronized (locks) {
// If, after failing to acquire the lock, no other thread is using the lock, discard it.
if (lock.decremementUseCount() == 0) {
locks.remove(t);
}
}
}
}
} finally {
if (previousInterruption) {
Thread.currentThread().interrupt();
}
}
}
public void unlock(T t) {
synchronized (locks) {
LockHolder lock = locks.get(t);
if (lock == null)
throw new IllegalStateException("No lock found."); //$NON-NLS-1$
lock.unlock();
// If, after unlocking, no other thread is using the lock, discard it.
if (lock.decremementUseCount() == 0) {
locks.remove(t);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy