Provide an optimized AtomicIntegerFieldUpdater, AtomicLongFieldUpdater and AtomicReferenceFieldUpdater
This commit is contained in:
parent
3d531231fe
commit
9bee78f91c
@ -26,8 +26,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
*/
|
||||
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
|
||||
private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater;
|
||||
|
||||
private static final long REFCNT_FIELD_OFFSET;
|
||||
|
||||
@ -43,6 +42,12 @@ public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
|
||||
}
|
||||
|
||||
REFCNT_FIELD_OFFSET = refCntFieldOffset;
|
||||
AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater =
|
||||
PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
|
||||
if (updater == null) {
|
||||
updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
|
||||
}
|
||||
refCntUpdater = updater;
|
||||
}
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
|
@ -24,8 +24,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
*/
|
||||
public abstract class AbstractReferenceCounted implements ReferenceCounted {
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<AbstractReferenceCounted> refCntUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCounted.class, "refCnt");
|
||||
private static final AtomicIntegerFieldUpdater<AbstractReferenceCounted> refCntUpdater;
|
||||
|
||||
private static final long REFCNT_FIELD_OFFSET;
|
||||
|
||||
@ -41,6 +40,13 @@ public abstract class AbstractReferenceCounted implements ReferenceCounted {
|
||||
}
|
||||
|
||||
REFCNT_FIELD_OFFSET = refCntFieldOffset;
|
||||
|
||||
AtomicIntegerFieldUpdater<AbstractReferenceCounted> updater =
|
||||
PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCounted.class, "refCnt");
|
||||
if (updater == null) {
|
||||
updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCounted.class, "refCnt");
|
||||
}
|
||||
refCntUpdater = updater;
|
||||
}
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.util;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -27,8 +29,17 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
public class DefaultAttributeMap implements AttributeMap {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, Map> updater =
|
||||
AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, Map.class, "map");
|
||||
private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, Map> updater;
|
||||
|
||||
static {
|
||||
@SuppressWarnings("rawtypes")
|
||||
AtomicReferenceFieldUpdater<DefaultAttributeMap, Map> referenceFieldUpdater =
|
||||
PlatformDependent.newAtomicReferenceFieldUpdater(DefaultAttributeMap.class, "map");
|
||||
if (referenceFieldUpdater == null) {
|
||||
referenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, Map.class, "map");
|
||||
}
|
||||
updater = referenceFieldUpdater;
|
||||
}
|
||||
|
||||
// Initialize lazily to reduce memory consumption; updated by AtomicReferenceFieldUpdater above.
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
|
@ -34,6 +34,9 @@ import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -296,6 +299,57 @@ public final class PlatformDependent {
|
||||
PlatformDependent0.copyMemory(null, srcAddr, dst, ARRAY_BASE_OFFSET + dstIndex, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optimized {@link AtomicReferenceFieldUpdater} or {@code null} if it
|
||||
* could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
|
||||
* use {@link AtomicReferenceFieldUpdater#newUpdater(Class, Class, String)} as fallback.
|
||||
*/
|
||||
public static <U, W> AtomicReferenceFieldUpdater<U, W> newAtomicReferenceFieldUpdater(
|
||||
Class<U> tclass, String fieldName) {
|
||||
if (hasUnsafe()) {
|
||||
try {
|
||||
return PlatformDependent0.newAtomicReferenceFieldUpdater(tclass, fieldName);
|
||||
} catch (Throwable ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optimized {@link AtomicIntegerFieldUpdater} or {@code null} if it
|
||||
* could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
|
||||
* use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback.
|
||||
*/
|
||||
public static <T> AtomicIntegerFieldUpdater<T> newAtomicIntegerFieldUpdater(
|
||||
Class<?> tclass, String fieldName) {
|
||||
if (hasUnsafe()) {
|
||||
try {
|
||||
return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName);
|
||||
} catch (Throwable ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optimized {@link AtomicLongFieldUpdater} or {@code null} if it
|
||||
* could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
|
||||
* use {@link AtomicLongFieldUpdater#newUpdater(Class, String)} as fallback.
|
||||
*/
|
||||
public static <T> AtomicLongFieldUpdater<T> newAtomicLongFieldUpdater(
|
||||
Class<?> tclass, String fieldName) {
|
||||
if (hasUnsafe()) {
|
||||
try {
|
||||
return PlatformDependent0.newAtomicLongFieldUpdater(tclass, fieldName);
|
||||
} catch (Throwable ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isAndroid0() {
|
||||
boolean android;
|
||||
try {
|
||||
|
@ -26,6 +26,9 @@ import java.lang.reflect.Method;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
/**
|
||||
* The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}.
|
||||
@ -312,6 +315,22 @@ final class PlatformDependent0 {
|
||||
UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, length);
|
||||
}
|
||||
|
||||
static <U, W> AtomicReferenceFieldUpdater<U, W> newAtomicReferenceFieldUpdater(
|
||||
Class<U> tclass, String fieldName) throws Exception {
|
||||
return new UnsafeAtomicReferenceFieldUpdater<U, W>(UNSAFE, tclass, fieldName);
|
||||
}
|
||||
|
||||
static <T> AtomicIntegerFieldUpdater<T> newAtomicIntegerFieldUpdater(
|
||||
Class<?> tclass, String fieldName) throws Exception {
|
||||
return new UnsafeAtomicIntegerFieldUpdater<T>(UNSAFE, tclass, fieldName);
|
||||
}
|
||||
|
||||
static <T> AtomicLongFieldUpdater<T> newAtomicLongFieldUpdater(
|
||||
Class<?> tclass, String fieldName) throws Exception {
|
||||
return new UnsafeAtomicLongFieldUpdater<T>(UNSAFE, tclass, fieldName);
|
||||
}
|
||||
|
||||
private PlatformDependent0() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
|
||||
final class UnsafeAtomicIntegerFieldUpdater<T> extends AtomicIntegerFieldUpdater<T> {
|
||||
private final long offset;
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class<?> tClass, String fieldName) throws NoSuchFieldException {
|
||||
Field field = tClass.getDeclaredField(fieldName);
|
||||
if (!Modifier.isVolatile(field.getModifiers())) {
|
||||
throw new IllegalArgumentException("Must be volatile");
|
||||
}
|
||||
this.unsafe = unsafe;
|
||||
offset = unsafe.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compareAndSet(T obj, int expect, int update) {
|
||||
return unsafe.compareAndSwapInt(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakCompareAndSet(T obj, int expect, int update) {
|
||||
return unsafe.compareAndSwapInt(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, int newValue) {
|
||||
unsafe.putIntVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazySet(T obj, int newValue) {
|
||||
unsafe.putOrderedInt(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(T obj) {
|
||||
return unsafe.getIntVolatile(obj, offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
|
||||
final class UnsafeAtomicLongFieldUpdater<T> extends AtomicLongFieldUpdater<T> {
|
||||
private final long offset;
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeAtomicLongFieldUpdater(Unsafe unsafe, Class<?> tClass, String fieldName) throws NoSuchFieldException {
|
||||
Field field = tClass.getDeclaredField(fieldName);
|
||||
if (!Modifier.isVolatile(field.getModifiers())) {
|
||||
throw new IllegalArgumentException("Must be volatile");
|
||||
}
|
||||
this.unsafe = unsafe;
|
||||
offset = unsafe.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compareAndSet(T obj, long expect, long update) {
|
||||
return unsafe.compareAndSwapLong(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakCompareAndSet(T obj, long expect, long update) {
|
||||
return unsafe.compareAndSwapLong(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T obj, long newValue) {
|
||||
unsafe.putLongVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazySet(T obj, long newValue) {
|
||||
unsafe.putOrderedLong(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long get(T obj) {
|
||||
return unsafe.getLongVolatile(obj, offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
final class UnsafeAtomicReferenceFieldUpdater<U, M> extends AtomicReferenceFieldUpdater<U, M> {
|
||||
private final long offset;
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeAtomicReferenceFieldUpdater(Unsafe unsafe, Class<U> tClass, String fieldName) throws NoSuchFieldException {
|
||||
Field field = tClass.getDeclaredField(fieldName);
|
||||
if (!Modifier.isVolatile(field.getModifiers())) {
|
||||
throw new IllegalArgumentException("Must be volatile");
|
||||
}
|
||||
this.unsafe = unsafe;
|
||||
offset = unsafe.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compareAndSet(U obj, M expect, M update) {
|
||||
return unsafe.compareAndSwapObject(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakCompareAndSet(U obj, M expect, M update) {
|
||||
return unsafe.compareAndSwapObject(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(U obj, M newValue) {
|
||||
unsafe.putObjectVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazySet(U obj, M newValue) {
|
||||
unsafe.putOrderedObject(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public M get(U obj) {
|
||||
return (M) unsafe.getObjectVolatile(obj, offset);
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.util.Recycler;
|
||||
import io.netty.util.Recycler.Handle;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
@ -78,13 +79,27 @@ public final class ChannelOutboundBuffer {
|
||||
|
||||
private boolean inFail;
|
||||
|
||||
private static final AtomicLongFieldUpdater<ChannelOutboundBuffer> TOTAL_PENDING_SIZE_UPDATER =
|
||||
AtomicLongFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "totalPendingSize");
|
||||
private static final AtomicLongFieldUpdater<ChannelOutboundBuffer> TOTAL_PENDING_SIZE_UPDATER;
|
||||
|
||||
private volatile long totalPendingSize;
|
||||
|
||||
private static final AtomicIntegerFieldUpdater<ChannelOutboundBuffer> WRITABLE_UPDATER =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "writable");
|
||||
private static final AtomicIntegerFieldUpdater<ChannelOutboundBuffer> WRITABLE_UPDATER;
|
||||
|
||||
static {
|
||||
AtomicIntegerFieldUpdater<ChannelOutboundBuffer> writableUpdater =
|
||||
PlatformDependent.newAtomicIntegerFieldUpdater(ChannelOutboundBuffer.class, "writable");
|
||||
if (writableUpdater == null) {
|
||||
writableUpdater = AtomicIntegerFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "writable");
|
||||
}
|
||||
WRITABLE_UPDATER = writableUpdater;
|
||||
|
||||
AtomicLongFieldUpdater<ChannelOutboundBuffer> pendingSizeUpdater =
|
||||
PlatformDependent.newAtomicLongFieldUpdater(ChannelOutboundBuffer.class, "totalPendingSize");
|
||||
if (pendingSizeUpdater == null) {
|
||||
pendingSizeUpdater = AtomicLongFieldUpdater.newUpdater(ChannelOutboundBuffer.class, "totalPendingSize");
|
||||
}
|
||||
TOTAL_PENDING_SIZE_UPDATER = pendingSizeUpdater;
|
||||
}
|
||||
|
||||
private volatile int writable = 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user