moved Util.lock to new class LockUtil which is not in domain.common and hence doesn't hurt the GWT build

This commit is contained in:
Axel Uhl committed 2012-07-24 00:51:25 +02:00
1 parent f82b87f87d
commit 45cb1db0f5
7 files changed
+61 -55

No files matched your search

@@ -4,42 +4,8 @@ import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.logging.Logger;
public class Util {
private static final int NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK = 5;
private static final Logger logger = Logger.getLogger(Util.class.getName());
/**
* Bug <a href="http://bugs.sun.com/view_bug.do?bug_id=6822370">http://bugs.sun.com/view_bug.do?bug_id=6822370</a> seems
* dangerous, particularly if it happens in a <code>LiveLeaderboardUpdater</code> thread. Even though the bug is reported to
* have been fixed in JDK 7(b79) we should be careful. This method tries to acquire a lock, allowing for five seconds to pass.
* After five seconds and not having retrieved the lock, tries again until the lock has been acquired.
* @throws InterruptedException
*/
public static void lock(Lock lock) {
boolean locked = false;
boolean interrupted = false;
while (!locked) {
try {
locked = lock.tryLock(NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK, TimeUnit.SECONDS);
if (!locked) {
logger.info("Couldn't acquire lock in "+NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK+"s. Trying again...");
}
}
catch (InterruptedException ex) {
interrupted = true;
}
}
if (interrupted) {
// re-assert interrupt state that occurred while we
// were acquiring the lock
Thread.currentThread().interrupt();
}
}
/**
* Adds all elements from <code>what</code> to <code>addTo</code> and returns <code>addTo</code> for chained use.
*/
@@ -24,8 +24,8 @@ import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.impl.NamedImpl;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.util.CourseAsWaypointList;
import com.sap.sailing.util.impl.LockUtil;
import difflib.DiffUtils;
import difflib.Patch;
@@ -69,7 +69,7 @@ public class CourseImpl extends NamedImpl implements Course {
@Override
public void lockForRead() {
Util.lock(lock.readLock());
LockUtil.lock(lock.readLock());
}
@Override
@@ -109,7 +109,7 @@ public class CourseImpl extends NamedImpl implements Course {
@Override
public void addWaypoint(int zeroBasedPosition, Waypoint waypointToAdd) {
Util.lock(lock.writeLock());
LockUtil.lock(lock.writeLock());
try {
waypoints.add(zeroBasedPosition, waypointToAdd);
Map<Waypoint, Integer> updatesToWaypointIndexes = new HashMap<Waypoint, Integer>();
@@ -139,7 +139,7 @@ public class CourseImpl extends NamedImpl implements Course {
public void removeWaypoint(int zeroBasedPosition) {
if (zeroBasedPosition >= 0) {
Waypoint removedWaypoint;
Util.lock(lock.writeLock());
LockUtil.lock(lock.writeLock());
try {
boolean isLast = zeroBasedPosition == waypoints.size() - 1;
removedWaypoint = waypoints.remove(zeroBasedPosition);
@@ -354,7 +354,7 @@ public class CourseImpl extends NamedImpl implements Course {
@Override
public void update(List<ControlPoint> newControlPoints, DomainFactory baseDomainFactory) throws PatchFailedException {
Util.lock(lock.writeLock());
LockUtil.lock(lock.writeLock());
try {
Iterable<Waypoint> courseWaypoints = getWaypoints();
List<Waypoint> newWaypointList = new LinkedList<Waypoint>();
@@ -26,7 +26,6 @@ import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.confidence.ConfidenceFactory;
import com.sap.sailing.domain.confidence.Weigher;
@@ -40,6 +39,7 @@ import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.WindWithConfidence;
import com.sap.sailing.util.SerializableComparator;
import com.sap.sailing.util.impl.ArrayListNavigableSet;
import com.sap.sailing.util.impl.LockUtil;
/**
* A virtual wind track that computes and caches the wind bearing based on the boat tracks recorded in the tracked race
@@ -183,7 +183,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
* Synchronizes serialization on this object to avoid the cache being updated while being written.
*/
private synchronized void writeObject(ObjectOutputStream s) throws IOException {
Util.lock(cacheLock.readLock());
LockUtil.lock(cacheLock.readLock());
lockForRead();
try {
s.defaultWriteObject();
@@ -228,7 +228,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
// can't use lockForWrite() here because caching can happen while holding the read lock, and the lock can't be
// upgraded. But lockForRead() and synchronization will do the job because all invalidations lock the write lock,
// and all contains() checks and get() calls use synchronization too.
Util.lock(cacheLock.writeLock());
LockUtil.lock(cacheLock.writeLock());
try {
// synchronization necessary to protect writeObject from ConcurrentModificationException
synchronized (this) {
@@ -240,7 +240,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
timePointsWithCachedNullResultFastContains.add(timePoint);
}
} else {
Util.lock(cacheLock.writeLock());
LockUtil.lock(cacheLock.writeLock());
try {
cache.add(fix);
} finally {
@@ -282,7 +282,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
* running.
*/
private void invalidateCache() {
Util.lock(cacheLock.writeLock());
LockUtil.lock(cacheLock.writeLock());
try {
Iterator<WindWithConfidence<TimePoint>> iter = (scheduledRefreshInterval.getStart() == null ? getCachedFixes()
: getCachedFixes().tailSet(scheduledRefreshInterval.getStart(), /* inclusive */true)).iterator();
@@ -318,7 +318,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
private void refreshCacheIncrementally() {
Set<WindWithConfidence<TimePoint>> windFixesToRecalculate = new HashSet<WindWithConfidence<TimePoint>>();
Set<TimePoint> cachedNullResultsToRecalculate = new HashSet<TimePoint>();
Util.lock(cacheLock.readLock());
LockUtil.lock(cacheLock.readLock());
try {
Iterator<WindWithConfidence<TimePoint>> iter = (scheduledRefreshInterval.getStart() == null ? getCachedFixes()
: getCachedFixes().tailSet(scheduledRefreshInterval.getStart(), /* inclusive */true)).iterator();
@@ -363,7 +363,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
}
}
// apply the computed cache deltas
Util.lock(cacheLock.writeLock());
LockUtil.lock(cacheLock.writeLock());
try {
for (TimePoint nullRemoval : nullRemovals) {
timePointsWithCachedNullResult.remove(nullRemoval);
@@ -403,7 +403,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
}
private void clearCache() {
Util.lock(cacheLock.writeLock());
LockUtil.lock(cacheLock.writeLock());
try {
cache.clear();
timePointsWithCachedNullResult.clear();
@@ -423,7 +423,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
WindWithConfidence<TimePoint> cachedFix = null;
WindWithConfidence<TimePoint> result = null;
final boolean nullResultCacheContains;
Util.lock(cacheLock.readLock());
LockUtil.lock(cacheLock.readLock());
try {
nullResultCacheContains = nullResultCacheContains(timePoint);
if (nullResultCacheContains) {
@@ -9,9 +9,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.tracking.Track;
import com.sap.sailing.util.impl.ArrayListNavigableSet;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.UnmodifiableNavigableSet;
public class TrackImpl<FixType extends Timed> implements Track<FixType> {
@@ -63,7 +63,7 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
@Override
public void lockForRead() {
Util.lock(readWriteLock.readLock());
LockUtil.lock(readWriteLock.readLock());
}
@Override
@@ -72,7 +72,7 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
}
protected void lockForWrite() {
Util.lock(readWriteLock.writeLock());
LockUtil.lock(readWriteLock.writeLock());
}
protected void unlockAfterWrite() {
@@ -82,6 +82,7 @@ import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.WindWithConfidence;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.SmartFutureCache;
import com.sap.sailing.util.impl.SmartFutureCache.AbstractCacheUpdater;
import com.sap.sailing.util.impl.SmartFutureCache.EmptyUpdateInterval;
@@ -755,7 +756,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
lock = readWriteLock.readLock();
}
}
Util.lock(lock);
LockUtil.lock(lock);
try {
if (rankedCompetitors == null) {
rankedCompetitors = competitorRankings.get(timePoint); // try again; maybe a writer released the write lock after updating the cache
@@ -0,0 +1,40 @@
package com.sap.sailing.util.impl;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.logging.Logger;
import com.sap.sailing.domain.common.impl.Util;
public class LockUtil {
private static final int NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK = 5;
private static final Logger logger = Logger.getLogger(Util.class.getName());
/**
* Bug <a href="http://bugs.sun.com/view_bug.do?bug_id=6822370">http://bugs.sun.com/view_bug.do?bug_id=6822370</a> seems
* dangerous, particularly if it happens in a <code>LiveLeaderboardUpdater</code> thread. Even though the bug is reported to
* have been fixed in JDK 7(b79) we should be careful. This method tries to acquire a lock, allowing for five seconds to pass.
* After five seconds and not having retrieved the lock, tries again until the lock has been acquired.
* @throws InterruptedException
*/
public static void lock(Lock lock) {
boolean locked = false;
boolean interrupted = false;
while (!locked) {
try {
locked = lock.tryLock(NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK, TimeUnit.SECONDS);
if (!locked) {
logger.info("Couldn't acquire lock in "+NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK+"s. Trying again...");
}
}
catch (InterruptedException ex) {
interrupted = true;
}
}
if (interrupted) {
// re-assert interrupt state that occurred while we
// were acquiring the lock
Thread.currentThread().interrupt();
}
}
}
@@ -12,7 +12,6 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Logger;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.util.impl.SmartFutureCache.UpdateInterval;
/**
@@ -193,7 +192,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> {
public V call() {
try {
V preResult = cacheUpdateComputer.computeCacheUpdate(key, joinedUpdateInterval);
Util.lock(getOrCreateLockForKey(key).writeLock());
LockUtil.lock(getOrCreateLockForKey(key).writeLock());
try {
V result = cacheUpdateComputer.provideNewCacheValue(key, cache.get(key), preResult, joinedUpdateInterval);
if (result == null) {
@@ -239,7 +238,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> {
}
} // else no calculation currently going on; value has been fetched from latest cache entry
} else {
Util.lock(getOrCreateLockForKey(key).readLock());
LockUtil.lock(getOrCreateLockForKey(key).readLock());
try {
value = cache.get(key);
} finally {