View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.buffer;
18  
19  import io.netty.util.Recycler;
20  import io.netty.util.internal.PlatformDependent;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.nio.ByteBuffer;
26  import java.nio.channels.ClosedChannelException;
27  import java.nio.channels.GatheringByteChannel;
28  import java.nio.channels.ScatteringByteChannel;
29  
30  final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
31      private static final Recycler<PooledUnsafeDirectByteBuf> RECYCLER = new Recycler<PooledUnsafeDirectByteBuf>() {
32          @Override
33          protected PooledUnsafeDirectByteBuf newObject(Handle handle) {
34              return new PooledUnsafeDirectByteBuf(handle, 0);
35          }
36      };
37  
38      static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) {
39          PooledUnsafeDirectByteBuf buf = RECYCLER.get();
40          buf.reuse(maxCapacity);
41          return buf;
42      }
43  
44      private long memoryAddress;
45  
46      private PooledUnsafeDirectByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) {
47          super(recyclerHandle, maxCapacity);
48      }
49  
50      @Override
51      void init(PoolChunk<ByteBuffer> chunk, long handle, int offset, int length, int maxLength,
52                PoolThreadCache cache) {
53          super.init(chunk, handle, offset, length, maxLength, cache);
54          initMemoryAddress();
55      }
56  
57      @Override
58      void initUnpooled(PoolChunk<ByteBuffer> chunk, int length) {
59          super.initUnpooled(chunk, length);
60          initMemoryAddress();
61      }
62  
63      private void initMemoryAddress() {
64          memoryAddress = PlatformDependent.directBufferAddress(memory) + offset;
65      }
66  
67      @Override
68      protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) {
69          return memory.duplicate();
70      }
71  
72      @Override
73      public boolean isDirect() {
74          return true;
75      }
76  
77      @Override
78      protected byte _getByte(int index) {
79          return UnsafeByteBufUtil.getByte(addr(index));
80      }
81  
82      @Override
83      protected short _getShort(int index) {
84          return UnsafeByteBufUtil.getShort(addr(index));
85      }
86  
87      @Override
88      protected int _getUnsignedMedium(int index) {
89          return UnsafeByteBufUtil.getUnsignedMedium(addr(index));
90      }
91  
92      @Override
93      protected int _getInt(int index) {
94          return UnsafeByteBufUtil.getInt(addr(index));
95      }
96  
97      @Override
98      protected long _getLong(int index) {
99          return UnsafeByteBufUtil.getLong(addr(index));
100     }
101 
102     @Override
103     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
104         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
105         return this;
106     }
107 
108     @Override
109     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
110         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
111         return this;
112     }
113 
114     @Override
115     public ByteBuf getBytes(int index, ByteBuffer dst) {
116         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
117         return this;
118     }
119 
120     @Override
121     public ByteBuf readBytes(ByteBuffer dst) {
122         int length = dst.remaining();
123         checkReadableBytes(length);
124         getBytes(readerIndex, dst);
125         readerIndex += length;
126         return this;
127     }
128 
129     @Override
130     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
131         UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
132         return this;
133     }
134 
135     @Override
136     public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
137         return getBytes(index, out, length, false);
138     }
139 
140     private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
141         checkIndex(index, length);
142         if (length == 0) {
143             return 0;
144         }
145 
146         ByteBuffer tmpBuf;
147         if (internal) {
148             tmpBuf = internalNioBuffer();
149         } else {
150             tmpBuf = memory.duplicate();
151         }
152         index = idx(index);
153         tmpBuf.clear().position(index).limit(index + length);
154         return out.write(tmpBuf);
155     }
156 
157     @Override
158     public int readBytes(GatheringByteChannel out, int length)
159             throws IOException {
160         checkReadableBytes(length);
161         int readBytes = getBytes(readerIndex, out, length, true);
162         readerIndex += readBytes;
163         return readBytes;
164     }
165 
166     @Override
167     protected void _setByte(int index, int value) {
168         UnsafeByteBufUtil.setByte(addr(index), (byte) value);
169     }
170 
171     @Override
172     protected void _setShort(int index, int value) {
173         UnsafeByteBufUtil.setShort(addr(index), value);
174     }
175 
176     @Override
177     protected void _setMedium(int index, int value) {
178         UnsafeByteBufUtil.setMedium(addr(index), value);
179     }
180 
181     @Override
182     protected void _setInt(int index, int value) {
183         UnsafeByteBufUtil.setInt(addr(index), value);
184     }
185 
186     @Override
187     protected void _setLong(int index, long value) {
188         UnsafeByteBufUtil.setLong(addr(index), value);
189     }
190 
191     @Override
192     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
193         UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
194         return this;
195     }
196 
197     @Override
198     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
199         UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
200         return this;
201     }
202 
203     @Override
204     public ByteBuf setBytes(int index, ByteBuffer src) {
205         UnsafeByteBufUtil.setBytes(this, addr(index), index, src);
206         return this;
207     }
208 
209     @Override
210     public int setBytes(int index, InputStream in, int length) throws IOException {
211         return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
212     }
213 
214     @Override
215     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
216         checkIndex(index, length);
217         ByteBuffer tmpBuf = internalNioBuffer();
218         index = idx(index);
219         tmpBuf.clear().position(index).limit(index + length);
220         try {
221             return in.read(tmpBuf);
222         } catch (ClosedChannelException ignored) {
223             return -1;
224         }
225     }
226 
227     @Override
228     public ByteBuf copy(int index, int length) {
229         return UnsafeByteBufUtil.copy(this, addr(index), index, length);
230     }
231 
232     @Override
233     public int nioBufferCount() {
234         return 1;
235     }
236 
237     @Override
238     public ByteBuffer[] nioBuffers(int index, int length) {
239         return new ByteBuffer[] { nioBuffer(index, length) };
240     }
241 
242     @Override
243     public ByteBuffer nioBuffer(int index, int length) {
244         checkIndex(index, length);
245         index = idx(index);
246         return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice();
247     }
248 
249     @Override
250     public ByteBuffer internalNioBuffer(int index, int length) {
251         checkIndex(index, length);
252         index = idx(index);
253         return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
254     }
255 
256     @Override
257     public boolean hasArray() {
258         return false;
259     }
260 
261     @Override
262     public byte[] array() {
263         throw new UnsupportedOperationException("direct buffer");
264     }
265 
266     @Override
267     public int arrayOffset() {
268         throw new UnsupportedOperationException("direct buffer");
269     }
270 
271     @Override
272     public boolean hasMemoryAddress() {
273         return true;
274     }
275 
276     @Override
277     public long memoryAddress() {
278         ensureAccessible();
279         return memoryAddress;
280     }
281 
282     private long addr(int index) {
283         return memoryAddress + index;
284     }
285 
286     @Override
287     protected Recycler<?> recycler() {
288         return RECYCLER;
289     }
290 
291     @Override
292     protected SwappedByteBuf newSwappedByteBuf() {
293         if (PlatformDependent.isUnaligned()) {
294             // Only use if unaligned access is supported otherwise there is no gain.
295             return new UnsafeDirectSwappedByteBuf(this);
296         }
297         return super.newSwappedByteBuf();
298     }
299 
300     @Override
301     public ByteBuf setZero(int index, int length) {
302         checkIndex(index, length);
303         UnsafeByteBufUtil.setZero(addr(index), length);
304         return this;
305     }
306 
307     @Override
308     public ByteBuf writeZero(int length) {
309         ensureWritable(length);
310         int wIndex = writerIndex;
311         UnsafeByteBufUtil.setZero(addr(wIndex), length);
312         writerIndex = wIndex + length;
313         return this;
314     }
315 }