RedissonList iterator race conditions #106

pull/110/head
Nikita 10 years ago
parent 1b3adef3a1
commit 983c34fadd

@ -223,6 +223,10 @@ public class RedissonList<V> extends RedissonExpirable implements RList<V> {
@Override @Override
public V get(final int index) { public V get(final int index) {
checkIndex(index); checkIndex(index);
return getValue(index);
}
private V getValue(final int index) {
return connectionManager.read(new ResultOperation<V, V>() { return connectionManager.read(new ResultOperation<V, V>() {
@Override @Override
protected Future<V> execute(RedisAsyncConnection<Object, V> async) { protected Future<V> execute(RedisAsyncConnection<Object, V> async) {
@ -374,50 +378,69 @@ public class RedissonList<V> extends RedissonExpirable implements RList<V> {
public ListIterator<V> listIterator(final int ind) { public ListIterator<V> listIterator(final int ind) {
return new ListIterator<V>() { return new ListIterator<V>() {
private V prevCurrentValue;
private V nextCurrentValue;
private V currentValueHasRead;
private int currentIndex = ind - 1; private int currentIndex = ind - 1;
private boolean removeExecuted; private boolean removeExecuted;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
int size = size(); V val = RedissonList.this.getValue(currentIndex+1);
return currentIndex+1 < size && size > 0; if (val != null) {
nextCurrentValue = val;
}
return val != null;
} }
@Override @Override
public V next() { public V next() {
if (!hasNext()) { if (nextCurrentValue == null && !hasNext()) {
throw new NoSuchElementException("No such element at index " + currentIndex); throw new NoSuchElementException("No such element at index " + currentIndex);
} }
currentIndex++; currentIndex++;
currentValueHasRead = nextCurrentValue;
nextCurrentValue = null;
removeExecuted = false; removeExecuted = false;
return RedissonList.this.get(currentIndex); return currentValueHasRead;
} }
@Override @Override
public void remove() { public void remove() {
if (currentValueHasRead == null) {
throw new IllegalStateException("Neither next nor previous have been called");
}
if (removeExecuted) { if (removeExecuted) {
throw new IllegalStateException("Element been already deleted"); throw new IllegalStateException("Element been already deleted");
} }
RedissonList.this.remove(currentIndex); RedissonList.this.remove(currentValueHasRead);
currentIndex--; currentIndex--;
removeExecuted = true; removeExecuted = true;
currentValueHasRead = null;
} }
@Override @Override
public boolean hasPrevious() { public boolean hasPrevious() {
int size = size(); if (currentIndex < 0) {
return currentIndex-1 < size && size > 0 && currentIndex >= 0; return false;
}
V val = RedissonList.this.getValue(currentIndex);
if (val != null) {
prevCurrentValue = val;
}
return val != null;
} }
@Override @Override
public V previous() { public V previous() {
if (!hasPrevious()) { if (prevCurrentValue == null && !hasPrevious()) {
throw new NoSuchElementException("No such element at index " + currentIndex); throw new NoSuchElementException("No such element at index " + currentIndex);
} }
removeExecuted = false;
V res = RedissonList.this.get(currentIndex);
currentIndex--; currentIndex--;
return res; removeExecuted = false;
currentValueHasRead = prevCurrentValue;
prevCurrentValue = null;
return currentValueHasRead;
} }
@Override @Override

Loading…
Cancel
Save