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.internal.ObjectPool;
20 import io.netty.util.internal.ObjectPool.Handle;
21 import io.netty.util.internal.ObjectPool.ObjectCreator;
22 import io.netty.util.internal.PlatformDependent;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.nio.ByteBuffer;
28
29 final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
30     private static final ObjectPool<PooledUnsafeDirectByteBuf> RECYCLER = ObjectPool.newPool(
31             new ObjectCreator<PooledUnsafeDirectByteBuf>() {
32         @Override
33         public PooledUnsafeDirectByteBuf newObject(Handle<PooledUnsafeDirectByteBuf> 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(Handle<PooledUnsafeDirectByteBuf> recyclerHandle, int maxCapacity) {
47         super(recyclerHandle, maxCapacity);
48     }
49
50     @Override
51     void init(PoolChunk<ByteBuffer> chunk, ByteBuffer nioBuffer,
52               long handle, int offset, int length, int maxLength, PoolThreadCache cache) {
53         super.init(chunk, nioBuffer, 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 short _getShortLE(int index) {
89         return UnsafeByteBufUtil.getShortLE(addr(index));
90     }
91
92     @Override
93     protected int _getUnsignedMedium(int index) {
94         return UnsafeByteBufUtil.getUnsignedMedium(addr(index));
95     }
96
97     @Override
98     protected int _getUnsignedMediumLE(int index) {
99         return UnsafeByteBufUtil.getUnsignedMediumLE(addr(index));
100     }
101
102     @Override
103     protected int _getInt(int index) {
104         return UnsafeByteBufUtil.getInt(addr(index));
105     }
106
107     @Override
108     protected int _getIntLE(int index) {
109         return UnsafeByteBufUtil.getIntLE(addr(index));
110     }
111
112     @Override
113     protected long _getLong(int index) {
114         return UnsafeByteBufUtil.getLong(addr(index));
115     }
116
117     @Override
118     protected long _getLongLE(int index) {
119         return UnsafeByteBufUtil.getLongLE(addr(index));
120     }
121
122     @Override
123     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
124         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
125         return this;
126     }
127
128     @Override
129     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
130         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
131         return this;
132     }
133
134     @Override
135     public ByteBuf getBytes(int index, ByteBuffer dst) {
136         UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
137         return this;
138     }
139
140     @Override
141     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
142         UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
143         return this;
144     }
145
146     @Override
147     protected void _setByte(int index, int value) {
148         UnsafeByteBufUtil.setByte(addr(index), (byte) value);
149     }
150
151     @Override
152     protected void _setShort(int index, int value) {
153         UnsafeByteBufUtil.setShort(addr(index), value);
154     }
155
156     @Override
157     protected void _setShortLE(int index, int value) {
158         UnsafeByteBufUtil.setShortLE(addr(index), value);
159     }
160
161     @Override
162     protected void _setMedium(int index, int value) {
163         UnsafeByteBufUtil.setMedium(addr(index), value);
164     }
165
166     @Override
167     protected void _setMediumLE(int index, int value) {
168         UnsafeByteBufUtil.setMediumLE(addr(index), value);
169     }
170
171     @Override
172     protected void _setInt(int index, int value) {
173         UnsafeByteBufUtil.setInt(addr(index), value);
174     }
175
176     @Override
177     protected void _setIntLE(int index, int value) {
178         UnsafeByteBufUtil.setIntLE(addr(index), value);
179     }
180
181     @Override
182     protected void _setLong(int index, long value) {
183         UnsafeByteBufUtil.setLong(addr(index), value);
184     }
185
186     @Override
187     protected void _setLongLE(int index, long value) {
188         UnsafeByteBufUtil.setLongLE(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 ByteBuf copy(int index, int length) {
216         return UnsafeByteBufUtil.copy(this, addr(index), index, length);
217     }
218
219     @Override
220     public boolean hasArray() {
221         return false;
222     }
223
224     @Override
225     public byte[] array() {
226         throw new UnsupportedOperationException("direct buffer");
227     }
228
229     @Override
230     public int arrayOffset() {
231         throw new UnsupportedOperationException("direct buffer");
232     }
233
234     @Override
235     public boolean hasMemoryAddress() {
236         return true;
237     }
238
239     @Override
240     public long memoryAddress() {
241         ensureAccessible();
242         return memoryAddress;
243     }
244
245     private long addr(int index) {
246         return memoryAddress + index;
247     }
248
249     @Override
250     protected SwappedByteBuf newSwappedByteBuf() {
251         if (PlatformDependent.isUnaligned()) {
252             // Only use if unaligned access is supported otherwise there is no gain.
253             return new UnsafeDirectSwappedByteBuf(this);
254         }
255         return super.newSwappedByteBuf();
256     }
257
258     @Override
259     public ByteBuf setZero(int index, int length) {
260         checkIndex(index, length);
261         UnsafeByteBufUtil.setZero(addr(index), length);
262         return this;
263     }
264
265     @Override
266     public ByteBuf writeZero(int length) {
267         ensureWritable(length);
268         int wIndex = writerIndex;
269         UnsafeByteBufUtil.setZero(addr(wIndex), length);
270         writerIndex = wIndex + length;
271         return this;
272     }
273 }
274