1. UserDataHolderBase can now use custom Map implementation for storing data

2. Made Language using its own ConcurrentMap in order for it to not depend on pooled locks from LockPoolSynchronizedMap
This commit is contained in:
Eugene Zhuravlev
2009-09-09 10:42:17 +04:00
parent 80a638020b
commit cef6526275
3 changed files with 48 additions and 8 deletions
@@ -19,8 +19,10 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ConcurrentHashMap;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -29,6 +31,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/**
* The base class for all programming language support implementations. Specific language implementations should inherit from this class
@@ -72,6 +75,10 @@ public abstract class Language extends UserDataHolderBase {
}
}
protected ConcurrentMap<Key, Object> createDataMap() {
return new ConcurrentHashMap<Key, Object>();
}
/**
* @return collection of all languages registered so far.
*/
@@ -6,13 +6,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
private static final Object MAP_LOCK = new Object();
private static final Object COPYABLE_MAP_LOCK = new Object();
private static final Key<Map<Key, Object>> COPYABLE_USER_MAP_KEY = Key.create("COPYABLE_USER_MAP_KEY");
private volatile LockPoolSynchronizedMap<Key, Object> myUserMap = null;
private volatile ConcurrentMap<Key, Object> myUserMap = null;
protected Object clone() {
try {
@@ -28,7 +29,7 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
}
public String getUserDataString() {
final Map<Key, Object> userMap = myUserMap;
final ConcurrentMap<Key, Object> userMap = myUserMap;
if (userMap == null) {
return "";
}
@@ -46,7 +47,7 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
other.myUserMap = null;
}
else {
LockPoolSynchronizedMap<Key, Object> fresh = createMap();
ConcurrentMap<Key, Object> fresh = createDataMap();
fresh.putAll(myUserMap);
other.myUserMap = fresh;
}
@@ -58,7 +59,7 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
}
public <T> void putUserData(Key<T> key, T value) {
LockPoolSynchronizedMap<Key, Object> map = getOrCreateMap();
Map<Key, Object> map = getOrCreateMap();
if (value == null) {
map.remove(key);
@@ -68,7 +69,7 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
}
}
private static LockPoolSynchronizedMap<Key, Object> createMap() {
protected ConcurrentMap<Key, Object> createDataMap() {
return new LockPoolSynchronizedMap<Key, Object>(2, 0.9f);
}
@@ -107,11 +108,11 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
}
private LockPoolSynchronizedMap<Key, Object> getOrCreateMap() {
private ConcurrentMap<Key, Object> getOrCreateMap() {
if (myUserMap == null) {
synchronized (MAP_LOCK) {
if (myUserMap == null) {
myUserMap = createMap();
myUserMap = createDataMap();
}
}
}
@@ -28,8 +28,9 @@ import gnu.trove.THashMap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> {
public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> implements ConcurrentMap<K, V> {
private static final int NUM_LOCKS = 256;
private static final JBReentrantReadWriteLock[] ourLocks = new JBReentrantReadWriteLock[NUM_LOCKS];
private static int ourLockAllocationCounter = 0;
@@ -211,6 +212,24 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> {
}
}
public V replace(K key, V newValue) {
w.lock();
try {
V prev = get(key);
if (newValue == null) {
remove(key);
}
else {
put(key, newValue);
}
return prev;
}
finally {
w.unlock();
}
}
public V putIfAbsent(K key, V value) {
w.lock();
try {
@@ -228,4 +247,17 @@ public class LockPoolSynchronizedMap<K, V> extends THashMap<K, V> {
}
}
public boolean remove(Object key, Object oldValue) {
w.lock();
try {
if (!Comparing.equal(oldValue, get(key))) {
return false;
}
return super.remove(key) != null;
}
finally {
w.unlock();
}
}
}