Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.net4j.util/src/org/eclipse')
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java17
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java29
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java110
3 files changed, 136 insertions, 20 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java
index 01f8d39f77..2b8a6218f0 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java
@@ -43,6 +43,23 @@ public final class ObjectUtil
return o.hashCode();
}
+ /**
+ * A collision-free hash code for small sets (<=4) of small, positive integers (<=128)
+ *
+ * @since 3.2
+ */
+ public static int hashCode(int... values)
+ {
+ int hash = 0;
+ for (int i = 0; i < values.length; i++)
+ {
+ hash += values[i];
+ hash = (hash << 7) - hash;
+ }
+
+ return hash;
+ }
+
public static int hashCode(long num)
{
return (int)(num >> 32) ^ (int)(num & 0xffffffff);
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java
new file mode 100644
index 0000000000..040ce5031f
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/IRWOLockManager.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) 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:
+ * Caspar De Groot - initial API and implementation
+ */
+package org.eclipse.net4j.util.concurrent;
+
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Caspar De Groot
+ * @since 3.2
+ */
+public interface IRWOLockManager<OBJECT, CONTEXT> extends IRWLockManager<OBJECT, CONTEXT>
+{
+ public List<LockState<OBJECT, CONTEXT>> lock2(LockType type, CONTEXT context,
+ Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException;
+
+ public List<LockState<OBJECT, CONTEXT>> unlock2(LockType type, CONTEXT context,
+ Collection<? extends OBJECT> objectsToUnlock);
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
index 979238a26a..846e9f3e35 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java
@@ -15,6 +15,7 @@ import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.collection.HashBag;
import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -33,20 +34,26 @@ import java.util.Set;
* @author Caspar De Groot
* @since 3.2
*/
-public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLockManager<OBJECT, CONTEXT>
+public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLockManager<OBJECT, CONTEXT>
{
- // TODO (CD) Ensure that CDOID and CDOIDandBranch have good hashCode implementations
+ private final List<LockState<OBJECT, CONTEXT>> EMPTY_RESULT = Collections.emptyList();
+
private final Map<OBJECT, LockState<OBJECT, CONTEXT>> objectToLockStateMap = createObjectToLocksMap();
- // TODO (CD) Ensure that IView has a good hashCode implementation
private final Map<CONTEXT, Set<LockState<OBJECT, CONTEXT>>> contextToLockStates = createContextToLocksMap();
public void lock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
throws InterruptedException
{
+ lock2(type, context, objectsToLock, timeout);
+ }
+
+ public List<LockState<OBJECT, CONTEXT>> lock2(LockType type, CONTEXT context,
+ Collection<? extends OBJECT> objectsToLock, long timeout) throws InterruptedException
+ {
if (objectsToLock.isEmpty())
{
- return;
+ return EMPTY_RESULT;
}
// Must come before the synchronized block!
@@ -56,7 +63,7 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
synchronized (this)
{
int count = objectsToLock.size();
- LockState<?, ?>[] lockStates = new LockState<?, ?>[count];
+ List<LockState<OBJECT, CONTEXT>> lockStates = new ArrayList<LockState<OBJECT, CONTEXT>>(count);
for (;;)
{
@@ -64,13 +71,12 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
{
for (int i = 0; i < count; i++)
{
- @SuppressWarnings("unchecked")
- LockState<OBJECT, CONTEXT> lockState = (LockState<OBJECT, CONTEXT>)lockStates[i];
+ LockState<OBJECT, CONTEXT> lockState = lockStates.get(i);
lockState.lock(type, context);
addLockToContext(context, lockState);
}
- return;
+ return lockStates;
}
wait(startTime, timeout);
@@ -86,9 +92,15 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
public synchronized void unlock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
{
+ unlock2(type, context, objectsToUnlock);
+ }
+
+ public synchronized List<LockState<OBJECT, CONTEXT>> unlock2(LockType type, CONTEXT context,
+ Collection<? extends OBJECT> objectsToUnlock)
+ {
if (objectsToUnlock.isEmpty())
{
- return;
+ return EMPTY_RESULT;
}
List<LockState<OBJECT, CONTEXT>> lockStates = new LinkedList<LockState<OBJECT, CONTEXT>>();
@@ -121,14 +133,21 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
}
notifyAll();
+
+ return lockStates;
}
public synchronized void unlock(CONTEXT context)
{
+ unlock2(context);
+ }
+
+ public synchronized List<LockState<OBJECT, CONTEXT>> unlock2(CONTEXT context)
+ {
Set<LockState<OBJECT, CONTEXT>> lockStates = contextToLockStates.get(context);
if (lockStates == null)
{
- return;
+ return EMPTY_RESULT;
}
List<OBJECT> objectsWithoutLocks = new LinkedList<OBJECT>();
@@ -141,8 +160,6 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
{
lockState.unlock(lockType, context);
}
-
- // TODO (CD) Consider whether WRITE_OPTIONs should be excluded from this...
}
if (lockState.hasNoLocks())
@@ -161,18 +178,35 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
}
notifyAll();
+
+ return toList(lockStates);
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<LockState<OBJECT, CONTEXT>> toList(Set<LockState<OBJECT, CONTEXT>> lockStates)
+ {
+ if (lockStates instanceof List)
+ {
+ return (List<LockState<OBJECT, CONTEXT>>)lockStates;
+ }
+
+ List<LockState<OBJECT, CONTEXT>> list = new LinkedList<LockState<OBJECT, CONTEXT>>();
+ for (LockState<OBJECT, CONTEXT> lockState : lockStates)
+ {
+ list.add(lockState);
+ }
+
+ return list;
}
public synchronized boolean hasLock(LockType type, CONTEXT context, OBJECT objectToLock)
{
- // TODO (CD) Should this be synced?
LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
return lockState != null && lockState.hasLock(type, context, false);
}
public synchronized boolean hasLockByOthers(LockType type, CONTEXT context, OBJECT objectToLock)
{
- // TODO (CD) Should this be synced?
LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(objectToLock);
return lockState != null && lockState.hasLock(type, context, true);
}
@@ -222,6 +256,11 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
return contextToLockStates;
}
+ public LockState<OBJECT, CONTEXT> getLockState(Object key)
+ {
+ return objectToLockStateMap.get(key);
+ }
+
private LockState<OBJECT, CONTEXT> getOrCreateLockState(OBJECT o)
{
LockState<OBJECT, CONTEXT> lockState = objectToLockStateMap.get(o);
@@ -235,10 +274,10 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
}
private boolean canLockInContext(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock,
- LockState<?, ?>[] lockStatesToFill)
+ List<LockState<OBJECT, CONTEXT>> lockStatesToFill)
{
Iterator<? extends OBJECT> it = objectsToLock.iterator();
- for (int i = 0; i < lockStatesToFill.length; i++)
+ for (int i = 0; i < objectsToLock.size(); i++)
{
OBJECT o = it.next();
LockState<OBJECT, CONTEXT> lockState = getOrCreateLockState(o);
@@ -247,7 +286,7 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
return false;
}
- lockStatesToFill[i] = lockState;
+ lockStatesToFill.add(lockState);
}
return true;
@@ -301,7 +340,7 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
/**
* Represents a combination of locks for one OBJECT. The different lock types are represented by the values of the
- * enum {@link LockType}.
+ * enum {@link IRWLockManager.LockType}
* <p>
* The locking semantics established by this class are as follows:
* <li>a read lock prevents a write lock by another, but allows read locks by others and allows a write option by
@@ -315,11 +354,10 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
* @author Caspar De Groot
* @since 3.2
*/
- protected static class LockState<OBJECT, CONTEXT>
+ public static class LockState<OBJECT, CONTEXT>
{
private final OBJECT lockedObject;
- // TODO (CD) Ensure that IView has a good hashCode implementation
private final HashBag<CONTEXT> readLockOwners = new HashBag<CONTEXT>();
private CONTEXT writeLockOwner;
@@ -374,6 +412,23 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
return false;
}
+ public boolean hasLock(org.eclipse.net4j.util.concurrent.IRWLockManager.LockType type)
+ {
+ switch (type)
+ {
+ case READ:
+ return readLockOwners.size() > 0;
+
+ case WRITE:
+ return writeLockOwner != null;
+
+ case OPTION:
+ return writeOptionOwner != null;
+ }
+
+ return false;
+ }
+
@Override
public String toString()
{
@@ -648,5 +703,20 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLoc
{
writeOptionOwner = null;
}
+
+ public Set<CONTEXT> getReadLockOwners()
+ {
+ return Collections.unmodifiableSet(readLockOwners);
+ }
+
+ public CONTEXT getWriteLockOwner()
+ {
+ return writeLockOwner;
+ }
+
+ public CONTEXT getWriteOptionOwner()
+ {
+ return writeOptionOwner;
+ }
}
}

Back to the top