src/Net/RefCountedByteBuffer.cs (45 lines of code) (raw):
// ------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// 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
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------
namespace Amqp
{
using System;
using System.Threading;
class RefCountedByteBuffer : ByteBuffer
{
readonly IBufferManager bufferManager;
int references;
internal RefCountedByteBuffer(IBufferManager bufferManager, byte[] buffer, int offset, int count, int length)
: base(buffer, offset, length, count, true)
{
this.bufferManager = bufferManager;
this.references = 1;
}
internal IBufferManager BufferManager
{
get { return this.bufferManager; }
}
internal override void AddReference()
{
if (Interlocked.Increment(ref this.references) <= 1)
{
Interlocked.Decrement(ref this.references);
throw new ObjectDisposedException(this.GetType().Name);
}
}
internal override void ReleaseReference()
{
if (Interlocked.Decrement(ref this.references) == 0)
{
this.bufferManager.ReturnBuffer(this.ToArraySegment());
}
}
internal override void DuplicateBuffer(int bufferSize, int dataSize, out byte[] buffer, out int offset, out int count)
{
var segment = this.bufferManager.TakeBuffer(bufferSize);
buffer = segment.Array;
offset = segment.Offset;
count = segment.Count;
System.Buffer.BlockCopy(this.Buffer, this.Start, segment.Array, segment.Offset, dataSize);
this.bufferManager.ReturnBuffer(this.ToArraySegment());
}
}
}