ByteBufUtil.isText method should be safe to be called concurrently
Motivation: ByteBufUtil.isText(...) may produce unexpected results if called concurrently on the same ByteBuffer. Modifications: - Don't use internalNioBuffer where it is not safe. - Add unit test. Result: ByteBufUtil.isText is thread-safe.
This commit is contained in:
parent
e72c197aa3
commit
d2bd36fc4c
@ -1151,9 +1151,9 @@ public final class ByteBufUtil {
|
||||
CharsetDecoder decoder = CharsetUtil.decoder(charset, CodingErrorAction.REPORT, CodingErrorAction.REPORT);
|
||||
try {
|
||||
if (buf.nioBufferCount() == 1) {
|
||||
decoder.decode(buf.internalNioBuffer(index, length));
|
||||
decoder.decode(buf.nioBuffer(index, length));
|
||||
} else {
|
||||
ByteBuf heapBuffer = buf.alloc().heapBuffer(length);
|
||||
ByteBuf heapBuffer = buf.alloc().heapBuffer(length);
|
||||
try {
|
||||
heapBuffer.writeBytes(buf, index, length);
|
||||
decoder.decode(heapBuffer.internalNioBuffer(heapBuffer.readerIndex(), length));
|
||||
|
@ -19,10 +19,15 @@ import io.netty.util.AsciiString;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static io.netty.buffer.Unpooled.unreleasableBuffer;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
@ -551,4 +556,44 @@ public class ByteBufUtilTest {
|
||||
buffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTextMultiThreaded() throws Throwable {
|
||||
final ByteBuf buffer = Unpooled.copiedBuffer("Hello, World!", CharsetUtil.ISO_8859_1);
|
||||
|
||||
try {
|
||||
final AtomicInteger counter = new AtomicInteger(60000);
|
||||
final AtomicReference<Throwable> errorRef = new AtomicReference<Throwable>();
|
||||
List<Thread> threads = new ArrayList<Thread>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (errorRef.get() == null && counter.decrementAndGet() > 0) {
|
||||
assertTrue(ByteBufUtil.isText(buffer, CharsetUtil.ISO_8859_1));
|
||||
}
|
||||
} catch (Throwable cause) {
|
||||
errorRef.compareAndSet(null, cause);
|
||||
}
|
||||
}
|
||||
});
|
||||
threads.add(thread);
|
||||
}
|
||||
for (Thread thread : threads) {
|
||||
thread.start();
|
||||
}
|
||||
|
||||
for (Thread thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
Throwable error = errorRef.get();
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
} finally {
|
||||
buffer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user