Remove DefaultCompositeByteBuf.lastAccessed and use binary search instead

- Fixes #1364
- Even if a user creates a duplicate/slice, lastAccessed was shared between the derived buffers and it's updated even by a read operation, which made multithread access impossible
This commit is contained in:
Trustin Lee 2013-05-17 16:54:47 +09:00
parent 7140e4e63b
commit f92cfba388

View File

@ -49,8 +49,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp
private final List<Component> components = new ArrayList<Component>(); private final List<Component> components = new ArrayList<Component>();
private final int maxNumComponents; private final int maxNumComponents;
private Component lastAccessed;
private int lastAccessedId;
private boolean freed; private boolean freed;
private Queue<ByteBuf> suspendedDeallocations; private Queue<ByteBuf> suspendedDeallocations;
@ -284,9 +282,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp
private void updateComponentOffsets(int cIndex) { private void updateComponentOffsets(int cIndex) {
Component c = components.get(cIndex); Component c = components.get(cIndex);
lastAccessed = c;
lastAccessedId = cIndex;
if (cIndex == 0) { if (cIndex == 0) {
c.offset = 0; c.offset = 0;
c.endOffset = c.length; c.endOffset = c.length;
@ -508,37 +503,19 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp
assert !freed; assert !freed;
checkIndex(offset); checkIndex(offset);
Component c = lastAccessed; for (int low = 0, high = components.size(); low <= high;) {
if (c == null) { int mid = low + high >>> 1;
lastAccessed = c = components.get(0); Component c = components.get(mid);
} if (offset >= c.endOffset) {
if (offset >= c.offset) { low = mid + 1;
if (offset < c.endOffset) { } else if (offset < c.offset) {
return lastAccessedId; high = mid - 1;
} } else {
return mid;
// Search right
for (int i = lastAccessedId + 1; i < components.size(); i ++) {
c = components.get(i);
if (offset < c.endOffset) {
lastAccessedId = i;
lastAccessed = c;
return i;
}
}
} else {
// Search left
for (int i = lastAccessedId - 1; i >= 0; i --) {
c = components.get(i);
if (offset >= c.offset) {
lastAccessedId = i;
lastAccessed = c;
return i;
}
} }
} }
throw new IllegalStateException("should not reach here - concurrent modification?"); throw new Error("should not reach here");
} }
@Override @Override
@ -982,38 +959,22 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp
assert !freed; assert !freed;
checkIndex(offset); checkIndex(offset);
Component c = lastAccessed; assert !freed;
if (c == null) { checkIndex(offset);
lastAccessed = c = components.get(0);
}
if (offset >= c.offset) { for (int low = 0, high = components.size(); low <= high;) {
if (offset < c.endOffset) { int mid = low + high >>> 1;
Component c = components.get(mid);
if (offset >= c.endOffset) {
low = mid + 1;
} else if (offset < c.offset) {
high = mid - 1;
} else {
return c; return c;
} }
// Search right
for (int i = lastAccessedId + 1; i < components.size(); i ++) {
c = components.get(i);
if (offset < c.endOffset) {
lastAccessedId = i;
lastAccessed = c;
return c;
}
}
} else {
// Search left
for (int i = lastAccessedId - 1; i >= 0; i --) {
c = components.get(i);
if (offset >= c.offset) {
lastAccessedId = i;
lastAccessed = c;
return c;
}
}
} }
throw new IllegalStateException("should not reach here - concurrent modification?"); throw new Error("should not reach here");
} }
@Override @Override