[#1668] Remove synchronized usage in JZlibEncoder and JdkZlibEncoder

This commit is contained in:
Norman Maurer 2013-07-29 07:08:49 +02:00
parent 3922c518cd
commit 6ce8571df3
2 changed files with 162 additions and 146 deletions

View File

@ -23,10 +23,11 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelPromiseNotifier;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.internal.EmptyArrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -35,7 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class JZlibEncoder extends ZlibEncoder {
private final Deflater z = new Deflater();
private final AtomicBoolean finished = new AtomicBoolean();
private volatile boolean finished;
private volatile ChannelHandlerContext ctx;
/**
@ -138,7 +139,6 @@ public class JZlibEncoder extends ZlibEncoder {
"allowed for compression.");
}
synchronized (z) {
int resultCode = z.init(
compressionLevel, windowBits, memLevel,
ZlibUtil.convertWrapperType(wrapper));
@ -146,7 +146,6 @@ public class JZlibEncoder extends ZlibEncoder {
ZlibUtil.fail(z, "initialization failure", resultCode);
}
}
}
/**
* Creates a new zlib encoder with the default compression level ({@code 6}),
@ -222,8 +221,6 @@ public class JZlibEncoder extends ZlibEncoder {
if (dictionary == null) {
throw new NullPointerException("dictionary");
}
synchronized (z) {
int resultCode;
resultCode = z.deflateInit(
compressionLevel, windowBits, memLevel,
@ -237,7 +234,6 @@ public class JZlibEncoder extends ZlibEncoder {
}
}
}
}
@Override
public ChannelFuture close() {
@ -245,8 +241,22 @@ public class JZlibEncoder extends ZlibEncoder {
}
@Override
public ChannelFuture close(ChannelPromise promise) {
return finishEncode(ctx(), promise);
public ChannelFuture close(final ChannelPromise promise) {
ChannelHandlerContext ctx = ctx();
EventExecutor executor = ctx.executor();
if (executor.inEventLoop()) {
return finishEncode(ctx, promise);
} else {
final ChannelPromise p = ctx.newPromise();
executor.execute(new Runnable() {
@Override
public void run() {
ChannelFuture f = finishEncode(ctx(), p);
f.addListener(new ChannelPromiseNotifier(promise));
}
});
return p;
}
}
private ChannelHandlerContext ctx() {
@ -259,16 +269,15 @@ public class JZlibEncoder extends ZlibEncoder {
@Override
public boolean isClosed() {
return finished.get();
return finished;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
if (finished.get()) {
if (finished) {
return;
}
synchronized (z) {
try {
// Configure input.
int inputLength = in.readableBytes();
@ -318,12 +327,11 @@ public class JZlibEncoder extends ZlibEncoder {
z.next_out = null;
}
}
}
@Override
public void close(
final ChannelHandlerContext ctx,
final ChannelPromise promise) throws Exception {
final ChannelPromise promise) {
ChannelFuture f = finishEncode(ctx, ctx.newPromise());
f.addListener(new ChannelFutureListener() {
@Override
@ -344,13 +352,13 @@ public class JZlibEncoder extends ZlibEncoder {
}
private ChannelFuture finishEncode(ChannelHandlerContext ctx, ChannelPromise promise) {
if (!finished.compareAndSet(false, true)) {
if (finished) {
promise.setSuccess();
return promise;
}
finished = true;
ByteBuf footer;
synchronized (z) {
try {
// Configure input.
z.next_in = EmptyArrays.EMPTY_BYTES;
@ -383,8 +391,6 @@ public class JZlibEncoder extends ZlibEncoder {
z.next_in = null;
z.next_out = null;
}
}
return ctx.writeAndFlush(footer, promise);
}

View File

@ -16,14 +16,14 @@
package io.netty.handler.codec.compression;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelPromiseNotifier;
import io.netty.util.concurrent.EventExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
@ -35,7 +35,7 @@ public class JdkZlibEncoder extends ZlibEncoder {
private final byte[] encodeBuf = new byte[8192];
private final Deflater deflater;
private final AtomicBoolean finished = new AtomicBoolean();
private volatile boolean finished;
private volatile ChannelHandlerContext ctx;
/*
@ -158,8 +158,22 @@ public class JdkZlibEncoder extends ZlibEncoder {
}
@Override
public ChannelFuture close(ChannelPromise future) {
return finishEncode(ctx(), future);
public ChannelFuture close(final ChannelPromise promise) {
ChannelHandlerContext ctx = ctx();
EventExecutor executor = ctx.executor();
if (executor.inEventLoop()) {
return finishEncode(ctx, promise);
} else {
final ChannelPromise p = ctx.newPromise();
executor.execute(new Runnable() {
@Override
public void run() {
ChannelFuture f = finishEncode(ctx(), p);
f.addListener(new ChannelPromiseNotifier(promise));
}
});
return p;
}
}
private ChannelHandlerContext ctx() {
@ -172,12 +186,12 @@ public class JdkZlibEncoder extends ZlibEncoder {
@Override
public boolean isClosed() {
return finished.get();
return finished;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
if (finished.get()) {
if (finished) {
out.writeBytes(in);
return;
}
@ -189,7 +203,6 @@ public class JdkZlibEncoder extends ZlibEncoder {
int sizeEstimate = (int) Math.ceil(inAry.length * 1.001) + 12;
out.ensureWritable(sizeEstimate);
synchronized (deflater) {
if (gzip) {
crc.update(inAry);
if (writeHeader) {
@ -204,7 +217,6 @@ public class JdkZlibEncoder extends ZlibEncoder {
out.writeBytes(encodeBuf, 0, numBytes);
}
}
}
@Override
public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
@ -228,13 +240,13 @@ public class JdkZlibEncoder extends ZlibEncoder {
}
private ChannelFuture finishEncode(final ChannelHandlerContext ctx, ChannelPromise promise) {
if (!finished.compareAndSet(false, true)) {
if (finished) {
promise.setSuccess();
return promise;
}
finished = true;
ByteBuf footer = ctx.alloc().buffer();
synchronized (deflater) {
deflater.finish();
while (!deflater.finished()) {
int numBytes = deflater.deflate(encodeBuf, 0, encodeBuf.length);
@ -253,8 +265,6 @@ public class JdkZlibEncoder extends ZlibEncoder {
footer.writeByte(uncBytes >>> 24);
}
deflater.end();
}
return ctx.writeAndFlush(footer, promise);
}