/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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. * */ using System; using System.Runtime.CompilerServices; namespace Qpid.Buffer { /** * A simplistic {@link ByteBufferAllocator} which simply allocates a new * buffer every time. */ public class SimpleByteBufferAllocator : ByteBufferAllocator { private const int MINIMUM_CAPACITY = 1; public SimpleByteBufferAllocator() { } public ByteBuffer allocate( int capacity, bool direct ) { FixedByteBuffer nioBuffer; if( direct ) { nioBuffer = FixedByteBuffer.allocateDirect( capacity ); } else { nioBuffer = FixedByteBuffer.allocate( capacity ); } return new SimpleByteBuffer( nioBuffer ); } public ByteBuffer wrap( FixedByteBuffer nioBuffer ) { return new SimpleByteBuffer( nioBuffer ); } public void dispose() { } private class SimpleByteBuffer : BaseByteBuffer { private FixedByteBuffer _buf; private int refCount = 1; internal SimpleByteBuffer( FixedByteBuffer buf ) { this._buf = buf; buf.order( ByteOrder.BigEndian ); refCount = 1; } [MethodImpl(MethodImplOptions.Synchronized)] public override void acquire() { if( refCount <= 0 ) { throw new InvalidOperationException("Already released buffer."); } refCount ++; } public override void release() { lock( this ) { if( refCount <= 0 ) { refCount = 0; throw new InvalidOperationException( "Already released buffer. You released the buffer too many times." ); } refCount --; if( refCount > 0) { return; } } } public override FixedByteBuffer buf() { return _buf; } public override bool isPooled() { return false; } public override void setPooled(bool pooled) { } protected override void capacity0(int requestedCapacity) { int newCapacity = MINIMUM_CAPACITY; while( newCapacity < requestedCapacity ) { newCapacity <<= 1; } FixedByteBuffer oldBuf = this._buf; FixedByteBuffer newBuf; if( isDirect() ) { newBuf = FixedByteBuffer.allocateDirect( newCapacity ); } else { newBuf = FixedByteBuffer.allocate( newCapacity ); } newBuf.clear(); oldBuf.clear(); newBuf.put( oldBuf ); this._buf = newBuf; } public override ByteBuffer duplicate() { return new SimpleByteBuffer( this._buf.duplicate() ); } public override ByteBuffer slice() { return new SimpleByteBuffer( this._buf.slice() ); } public override ByteBuffer asReadOnlyBuffer() { return new SimpleByteBuffer( this._buf.asReadOnlyBuffer() ); } public override byte[] array() { return _buf.array(); } public override int arrayOffset() { return _buf.arrayOffset(); } public override void put(ushort value) { _buf.put(value); } public override void put(uint max) { _buf.put(max); } public override void put(ulong tag) { _buf.put(tag); } public override ulong GetUnsignedLong() { return _buf.getUnsignedLong(); } } } }