All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.rubyeye.xmemcached.buffer.CachedBufferAllocator Maven / Gradle / Ivy

/**
 * Copyright [2009-2010] [dennis zhuang([email protected])] Licensed 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
 */
/**
 * Copyright [2009-2010] [dennis zhuang([email protected])] Licensed 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 net.rubyeye.xmemcached.buffer;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import net.rubyeye.xmemcached.utils.ByteUtils;
import com.google.code.yanf4j.util.CircularQueue;

/**
 * Cached IoBuffer allocator,cached buffer in ThreadLocal.
 * 
 * @author dennis
 * 
 */
@Deprecated
public class CachedBufferAllocator implements BufferAllocator {

  private static final int DEFAULT_MAX_POOL_SIZE = 8;
  private static final int DEFAULT_MAX_CACHED_BUFFER_SIZE = 1 << 18; // 256KB
  private final int maxPoolSize;
  private final int maxCachedBufferSize;
  private final ThreadLocal>> heapBuffers;
  private final IoBuffer EMPTY_IO_BUFFER =
      new CachedBufferAllocator.CachedIoBuffer(ByteBuffer.allocate(0));

  /**
   * Creates a new instance with the default parameters ({@literal #DEFAULT_MAX_POOL_SIZE} and
   * {@literal #DEFAULT_MAX_CACHED_BUFFER_SIZE}).
   */
  public CachedBufferAllocator() {
    this(DEFAULT_MAX_POOL_SIZE, DEFAULT_MAX_CACHED_BUFFER_SIZE);
  }

  /**
   * Creates a new instance.
   * 
   * @param maxPoolSize the maximum number of buffers with the same capacity per thread. 0
   *        disables this limitation.
   * @param maxCachedBufferSize the maximum capacity of a cached buffer. A buffer whose capacity is
   *        bigger than this value is not pooled. 0 disables this limitation.
   */
  public CachedBufferAllocator(int maxPoolSize, int maxCachedBufferSize) {
    if (maxPoolSize < 0) {
      throw new IllegalArgumentException("maxPoolSize: " + maxPoolSize);
    }
    if (maxCachedBufferSize < 0) {
      throw new IllegalArgumentException("maxCachedBufferSize: " + maxCachedBufferSize);
    }

    this.maxPoolSize = maxPoolSize;
    this.maxCachedBufferSize = maxCachedBufferSize;

    this.heapBuffers = new ThreadLocal>>() {

      @Override
      protected Map> initialValue() {
        return newPoolMap();
      }
    };
  }

  public int getMaxPoolSize() {
    return this.maxPoolSize;
  }

  public int getMaxCachedBufferSize() {
    return this.maxCachedBufferSize;
  }

  /**
   * 初始化缓冲池
   * 
   * @return
   */
  private Map> newPoolMap() {
    Map> poolMap = new HashMap>();
    int poolSize = this.maxPoolSize == 0 ? DEFAULT_MAX_POOL_SIZE : this.maxPoolSize;
    for (int i = 0; i < 31; i++) {
      poolMap.put(1 << i, new CircularQueue(poolSize));
    }
    poolMap.put(0, new CircularQueue(poolSize));
    poolMap.put(Integer.MAX_VALUE, new CircularQueue(poolSize));
    return poolMap;
  }

  public final IoBuffer allocate(int requestedCapacity) {
    if (requestedCapacity == 0) {
      return this.EMPTY_IO_BUFFER;
    }
    // 圆整requestedCapacity到2的x次方
    int actualCapacity = ByteUtils.normalizeCapacity(requestedCapacity);
    IoBuffer buf;
    if (this.maxCachedBufferSize != 0 && actualCapacity > this.maxCachedBufferSize) {
      buf = wrap(ByteBuffer.allocate(actualCapacity));
    } else {
      Queue pool;
      pool = this.heapBuffers.get().get(actualCapacity);
      // 从池中取
      buf = pool.poll();
      if (buf != null) {
        buf.clear();
      } else {
        buf = wrap(ByteBuffer.allocate(actualCapacity));
      }
    }
    buf.limit(requestedCapacity);
    return buf;
  }

  public final IoBuffer wrap(ByteBuffer nioBuffer) {
    return new CachedIoBuffer(nioBuffer);
  }

  public void dispose() {
    this.heapBuffers.remove();
  }

  public static BufferAllocator newInstance() {
    return new CachedBufferAllocator();
  }

  public static BufferAllocator newInstance(int maxPoolSize, int maxCachedBufferSize) {
    return new CachedBufferAllocator(maxPoolSize, maxCachedBufferSize);
  }

  public class CachedIoBuffer implements IoBuffer {

    Thread ownerThread; // 所分配的线程
    ByteBuffer origBuffer;

    public CachedIoBuffer(ByteBuffer origBuffer) {
      super();
      this.ownerThread = Thread.currentThread();
      this.origBuffer = origBuffer;
    }

    public void putInt(int i) {
      this.origBuffer.putInt(i);

    }

    public void putShort(short s) {
      this.origBuffer.putShort(s);
    }

    public ByteOrder order() {
      return this.origBuffer.order();
    }

    public boolean isDirect() {
      return this.origBuffer.isDirect();
    }

    public void order(ByteOrder byteOrder) {
      this.origBuffer.order(byteOrder);
    }

    public void putLong(long l) {
      this.origBuffer.putLong(l);

    }

    public final void free() {
      if (this.origBuffer == null
          || this.origBuffer.capacity() > CachedBufferAllocator.this.maxCachedBufferSize
          || Thread.currentThread() != this.ownerThread) {
        return;
      }

      // Add to the cache.
      Queue pool;
      pool = CachedBufferAllocator.this.heapBuffers.get().get(this.origBuffer.capacity());
      if (pool == null) {
        return;
      }
      // 防止OOM
      if (CachedBufferAllocator.this.maxPoolSize == 0
          || pool.size() < CachedBufferAllocator.this.maxPoolSize) {
        pool.offer(new CachedIoBuffer(this.origBuffer));
      }
      this.origBuffer = null;

    }

    public final ByteBuffer[] getByteBuffers() {
      return new ByteBuffer[] {this.origBuffer};
    }

    public final void put(byte[] bytes) {
      this.origBuffer.put(bytes);
    }

    public final int capacity() {
      return this.origBuffer.capacity();
    }

    public final void clear() {
      this.origBuffer.clear();
    }

    public final void reset() {
      this.origBuffer.reset();
    }

    public final int remaining() {
      return this.origBuffer.remaining();
    }

    public final int position() {
      return this.origBuffer.position();
    }

    public final void mark() {
      this.origBuffer.mark();
    }

    public final int limit() {
      return this.origBuffer.limit();
    }

    public final boolean hasRemaining() {
      return this.origBuffer.hasRemaining();
    }

    public final void flip() {
      this.origBuffer.flip();
    }

    public final void put(byte b) {
      this.origBuffer.put(b);
    }

    public final void put(ByteBuffer buff) {
      this.origBuffer.put(buff);
    }

    public final ByteBuffer getByteBuffer() {
      return this.origBuffer;
    }

    public final void limit(int limit) {
      this.origBuffer.limit(limit);
    }

    public final void position(int pos) {
      this.origBuffer.position(pos);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy