mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
read/write lock instead of synchronized
This commit is contained in:
@@ -18,12 +18,14 @@ package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.concurrency.JBLock;
|
||||
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
|
||||
import com.intellij.util.concurrency.LockFactory;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This storage is needed for indexing yet unsaved data without saving those changes to 'main' backend storage
|
||||
@@ -34,10 +36,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value> {
|
||||
private final Map<Key, UpdatableValueContainer<Value>> myMap = new HashMap<Key,UpdatableValueContainer<Value>>();
|
||||
private final IndexStorage<Key, Value> myBackendStorage;
|
||||
private final AtomicBoolean myBufferingEnabled = new AtomicBoolean(false);
|
||||
private boolean myBufferingEnabled = false;
|
||||
private final List<BufferingStateListener> myListeners = ContainerUtil.createEmptyCOWList();
|
||||
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
|
||||
private final JBLock r = myLock.readLock();
|
||||
private final JBLock w = myLock.writeLock();
|
||||
|
||||
public static interface BufferingStateListener {
|
||||
public interface BufferingStateListener {
|
||||
void bufferingStateChanged(boolean newState);
|
||||
}
|
||||
|
||||
@@ -53,15 +58,22 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
myListeners.remove(listener);
|
||||
}
|
||||
|
||||
public synchronized void setBufferingEnabled(boolean enabled) {
|
||||
final boolean wasEnabled = myBufferingEnabled.getAndSet(enabled);
|
||||
if (wasEnabled && !enabled) {
|
||||
myMap.clear();
|
||||
}
|
||||
if (wasEnabled != enabled) {
|
||||
for (BufferingStateListener listener : myListeners) {
|
||||
listener.bufferingStateChanged(enabled);
|
||||
public void setBufferingEnabled(boolean enabled) {
|
||||
w.lock();
|
||||
try {
|
||||
final boolean wasEnabled = myBufferingEnabled;
|
||||
myBufferingEnabled = enabled;
|
||||
if (wasEnabled && !enabled) {
|
||||
myMap.clear();
|
||||
}
|
||||
if (wasEnabled != enabled) {
|
||||
for (BufferingStateListener listener : myListeners) {
|
||||
listener.bufferingStateChanged(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +81,15 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
myBackendStorage.close();
|
||||
}
|
||||
|
||||
public synchronized void clear() throws StorageException {
|
||||
myMap.clear();
|
||||
myBackendStorage.clear();
|
||||
public void clear() throws StorageException {
|
||||
w.lock();
|
||||
try {
|
||||
myMap.clear();
|
||||
myBackendStorage.clear();
|
||||
}
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
@@ -84,58 +102,80 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
return keys;
|
||||
}
|
||||
|
||||
public synchronized boolean processKeys(final Processor<Key> processor) throws StorageException {
|
||||
if (myBufferingEnabled.get()) {
|
||||
final Set<Key> stopList = new HashSet<Key>();
|
||||
public boolean processKeys(final Processor<Key> processor) throws StorageException {
|
||||
r.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
final Set<Key> stopList = new HashSet<Key>();
|
||||
|
||||
Processor<Key> decoratingProcessor = new Processor<Key>() {
|
||||
public boolean process(final Key key) {
|
||||
if (stopList.contains(key)) return true;
|
||||
Processor<Key> decoratingProcessor = new Processor<Key>() {
|
||||
public boolean process(final Key key) {
|
||||
if (stopList.contains(key)) return true;
|
||||
|
||||
final UpdatableValueContainer<Value> container = myMap.get(key);
|
||||
if (container != null && container.size() == 0) return true;
|
||||
return processor.process(key);
|
||||
final UpdatableValueContainer<Value> container = myMap.get(key);
|
||||
if (container != null && container.size() == 0) return true;
|
||||
return processor.process(key);
|
||||
}
|
||||
};
|
||||
|
||||
for (Key key : myMap.keySet()) {
|
||||
if (!decoratingProcessor.process(key)) return false;
|
||||
stopList.add(key);
|
||||
}
|
||||
};
|
||||
|
||||
for (Key key : myMap.keySet()) {
|
||||
if (!decoratingProcessor.process(key)) return false;
|
||||
stopList.add(key);
|
||||
return myBackendStorage.processKeys(decoratingProcessor);
|
||||
}
|
||||
return myBackendStorage.processKeys(decoratingProcessor);
|
||||
}
|
||||
else {
|
||||
return myBackendStorage.processKeys(processor);
|
||||
finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
return myBackendStorage.processKeys(processor);
|
||||
}
|
||||
|
||||
public void addValue(final Key key, final int inputId, final Value value) throws StorageException {
|
||||
if (!myBufferingEnabled.get()) {
|
||||
myBackendStorage.addValue(key, inputId, value);
|
||||
return;
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).addValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getMemValueContainer(key).addValue(inputId, value);
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
|
||||
myBackendStorage.addValue(key, inputId, value);
|
||||
}
|
||||
|
||||
public void removeValue(final Key key, final int inputId, final Value value) throws StorageException {
|
||||
if (myBufferingEnabled.get()) {
|
||||
getMemValueContainer(key).removeValue(inputId, value);
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).removeValue(inputId, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myBackendStorage.removeValue(key, inputId, value);
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
myBackendStorage.removeValue(key, inputId, value);
|
||||
}
|
||||
|
||||
public void removeAllValues(Key key, int inputId) throws StorageException {
|
||||
if (myBufferingEnabled.get()) {
|
||||
getMemValueContainer(key).removeAllValues(inputId);
|
||||
w.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
getMemValueContainer(key).removeAllValues(inputId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myBackendStorage.removeAllValues(key, inputId);
|
||||
finally {
|
||||
w.unlock();
|
||||
}
|
||||
myBackendStorage.removeAllValues(key, inputId);
|
||||
}
|
||||
|
||||
private synchronized UpdatableValueContainer<Value> getMemValueContainer(final Key key) {
|
||||
private UpdatableValueContainer<Value> getMemValueContainer(final Key key) {
|
||||
UpdatableValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer == null) {
|
||||
valueContainer = new ChangeTrackingValueContainer<Value>(new ChangeTrackingValueContainer.Initializer<Value>() {
|
||||
@@ -158,14 +198,21 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public synchronized ValueContainer<Value> read(final Key key) throws StorageException {
|
||||
if (!myBufferingEnabled.get()) {
|
||||
return myBackendStorage.read(key);
|
||||
public ValueContainer<Value> read(final Key key) throws StorageException {
|
||||
r.lock();
|
||||
try {
|
||||
if (myBufferingEnabled) {
|
||||
final ValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
return valueContainer;
|
||||
}
|
||||
return myBackendStorage.read(key);
|
||||
}
|
||||
}
|
||||
final ValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
return valueContainer;
|
||||
finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
return myBackendStorage.read(key);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user