/*
 * Copyright 2013 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.buffer;

import io.netty.util.ResourceLeakDetector;
import io.netty.util.ResourceLeakTracker;
import io.netty.util.internal.ObjectUtil;

import java.nio.ByteOrder;

class SimpleLeakAwareByteBuf extends WrappedByteBuf {

    
This object's is associated with the ResourceLeakTracker. When ResourceLeakTracker.close(Object) is called this object will be used as the argument. It is also assumed that this object is used when ResourceLeakDetector.track(Object) is called to create leak.
/** * This object's is associated with the {@link ResourceLeakTracker}. When {@link ResourceLeakTracker#close(Object)} * is called this object will be used as the argument. It is also assumed that this object is used when * {@link ResourceLeakDetector#track(Object)} is called to create {@link #leak}. */
private final ByteBuf trackedByteBuf; final ResourceLeakTracker<ByteBuf> leak; SimpleLeakAwareByteBuf(ByteBuf wrapped, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leak) { super(wrapped); this.trackedByteBuf = ObjectUtil.checkNotNull(trackedByteBuf, "trackedByteBuf"); this.leak = ObjectUtil.checkNotNull(leak, "leak"); } SimpleLeakAwareByteBuf(ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leak) { this(wrapped, wrapped, leak); } @Override public ByteBuf slice() { return newSharedLeakAwareByteBuf(super.slice()); } @Override public ByteBuf retainedSlice() { return unwrappedDerived(super.retainedSlice()); } @Override public ByteBuf retainedSlice(int index, int length) { return unwrappedDerived(super.retainedSlice(index, length)); } @Override public ByteBuf retainedDuplicate() { return unwrappedDerived(super.retainedDuplicate()); } @Override public ByteBuf readRetainedSlice(int length) { return unwrappedDerived(super.readRetainedSlice(length)); } @Override public ByteBuf slice(int index, int length) { return newSharedLeakAwareByteBuf(super.slice(index, length)); } @Override public ByteBuf duplicate() { return newSharedLeakAwareByteBuf(super.duplicate()); } @Override public ByteBuf readSlice(int length) { return newSharedLeakAwareByteBuf(super.readSlice(length)); } @Override public ByteBuf asReadOnly() { return newSharedLeakAwareByteBuf(super.asReadOnly()); } @Override public ByteBuf touch() { return this; } @Override public ByteBuf touch(Object hint) { return this; } @Override public boolean release() { if (super.release()) { closeLeak(); return true; } return false; } @Override public boolean release(int decrement) { if (super.release(decrement)) { closeLeak(); return true; } return false; } private void closeLeak() { // Close the ResourceLeakTracker with the tracked ByteBuf as argument. This must be the same that was used when // calling DefaultResourceLeak.track(...). boolean closed = leak.close(trackedByteBuf); assert closed; } @Override public ByteBuf order(ByteOrder endianness) { if (order() == endianness) { return this; } else { return newSharedLeakAwareByteBuf(super.order(endianness)); } } private ByteBuf unwrappedDerived(ByteBuf derived) { // We only need to unwrap SwappedByteBuf implementations as these will be the only ones that may end up in // the AbstractLeakAwareByteBuf implementations beside slices / duplicates and "real" buffers. ByteBuf unwrappedDerived = unwrapSwapped(derived); if (unwrappedDerived instanceof AbstractPooledDerivedByteBuf) { // Update the parent to point to this buffer so we correctly close the ResourceLeakTracker. ((AbstractPooledDerivedByteBuf) unwrappedDerived).parent(this); ResourceLeakTracker<ByteBuf> newLeak = AbstractByteBuf.leakDetector.track(derived); if (newLeak == null) { // No leak detection, just return the derived buffer. return derived; } return newLeakAwareByteBuf(derived, newLeak); } return newSharedLeakAwareByteBuf(derived); } @SuppressWarnings("deprecation") private static ByteBuf unwrapSwapped(ByteBuf buf) { if (buf instanceof SwappedByteBuf) { do { buf = buf.unwrap(); } while (buf instanceof SwappedByteBuf); return buf; } return buf; } private SimpleLeakAwareByteBuf newSharedLeakAwareByteBuf( ByteBuf wrapped) { return newLeakAwareByteBuf(wrapped, trackedByteBuf, leak); } private SimpleLeakAwareByteBuf newLeakAwareByteBuf( ByteBuf wrapped, ResourceLeakTracker<ByteBuf> leakTracker) { return newLeakAwareByteBuf(wrapped, wrapped, leakTracker); } protected SimpleLeakAwareByteBuf newLeakAwareByteBuf( ByteBuf buf, ByteBuf trackedByteBuf, ResourceLeakTracker<ByteBuf> leakTracker) { return new SimpleLeakAwareByteBuf(buf, trackedByteBuf, leakTracker); } }