View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.io;
20  
21  import java.nio.ByteBuffer;
22  import java.util.concurrent.ConcurrentHashMap;
23  import java.util.concurrent.ConcurrentMap;
24  import java.util.concurrent.atomic.AtomicInteger;
25  
26  import org.eclipse.jetty.util.BufferUtil;
27  
28  public class MappedByteBufferPool implements ByteBufferPool
29  {
30      private final ConcurrentMap<Integer, Bucket> directBuffers = new ConcurrentHashMap<>();
31      private final ConcurrentMap<Integer, Bucket> heapBuffers = new ConcurrentHashMap<>();
32      private final int _factor;
33      private final int _maxQueue;
34  
35      public MappedByteBufferPool()
36      {
37          this(-1);
38      }
39  
40      public MappedByteBufferPool(int factor)
41      {
42          this(factor,-1);
43      }
44      
45      public MappedByteBufferPool(int factor,int maxQueue)
46      {
47          _factor = factor<=0?1024:factor;
48          _maxQueue=maxQueue;
49      }
50  
51      @Override
52      public ByteBuffer acquire(int size, boolean direct)
53      {
54          int b = bucketFor(size);
55          ConcurrentMap<Integer, Bucket> buffers = bucketsFor(direct);
56  
57          Bucket bucket = buffers.get(b);
58          if (bucket==null)
59              return newByteBuffer(b*_factor, direct);
60          return bucket.acquire(direct);
61      }
62  
63      protected ByteBuffer newByteBuffer(int capacity, boolean direct)
64      {
65          return direct ? BufferUtil.allocateDirect(capacity)
66                        : BufferUtil.allocate(capacity);
67      }
68  
69      @Override
70      public void release(ByteBuffer buffer)
71      {
72          if (buffer == null)
73              return; // nothing to do
74          
75          // validate that this buffer is from this pool
76          assert((buffer.capacity() % _factor) == 0);
77          
78          int b = bucketFor(buffer.capacity());
79          ConcurrentMap<Integer, Bucket> buckets = bucketsFor(buffer.isDirect());
80  
81          Bucket bucket = buckets.computeIfAbsent(b,bi->new Bucket(b*_factor,_maxQueue));
82          bucket.release(buffer);
83      }
84  
85      public void clear()
86      {
87          directBuffers.clear();
88          heapBuffers.clear();
89      }
90  
91      private int bucketFor(int size)
92      {
93          int bucket = size / _factor;
94          if (size % _factor > 0)
95              ++bucket;
96          return bucket;
97      }
98  
99      // Package local for testing
100     ConcurrentMap<Integer, Bucket> bucketsFor(boolean direct)
101     {
102         return direct ? directBuffers : heapBuffers;
103     }
104 
105     public static class Tagged extends MappedByteBufferPool
106     {
107         private final AtomicInteger tag = new AtomicInteger();
108 
109         @Override
110         protected ByteBuffer newByteBuffer(int capacity, boolean direct)
111         {
112             ByteBuffer buffer = super.newByteBuffer(capacity + 4, direct);
113             buffer.limit(buffer.capacity());
114             buffer.putInt(tag.incrementAndGet());
115             ByteBuffer slice = buffer.slice();
116             BufferUtil.clear(slice);
117             return slice;
118         }
119     }
120 }