- // ==++==
- //
- //
- // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
- //
- // The use and distribution terms for this software are contained in the file
- // named license.txt, which can be found in the root of this distribution.
- // By using this software in any fashion, you are agreeing to be bound by the
- // terms of this license.
- //
- // You must not remove this notice, or any other, from this software.
- //
- //
- // ==--==
- //==========================================================================
- // File: ByteBufferPool.cs
- //
- // Summary: Stream used for reading from a socket by remoting channels.
- //
- //==========================================================================
- using System;
- using System.Threading;
- namespace System.IO
- {
- internal interface IByteBufferPool
- {
- byte[] GetBuffer();
- void ReturnBuffer(byte[] buffer);
- }
- // This isn't actually a buffer pool. It always creates a new byte buffer.
- internal class ByteBufferAllocator : IByteBufferPool
- {
- private int _bufferSize;
- public ByteBufferAllocator(int bufferSize)
- {
- _bufferSize = bufferSize;
- }
- public byte[] GetBuffer()
- {
- return new byte[_bufferSize];
- }
- public void ReturnBuffer(byte[] buffer)
- {
- }
- } // ByteBufferAllocator
- internal class ByteBufferPool : IByteBufferPool
- {
- private byte[][] _bufferPool = null;
- private int _current; // -1 for none
- private int _last;
- private int _max; // maximum number of buffers to pool
- private int _bufferSize;
- private Object _controlCookie = "cookie object";
- public ByteBufferPool(int maxBuffers, int bufferSize)
- {
- _max = maxBuffers;
- _bufferPool = new byte[_max][];
- _bufferSize = bufferSize;
- _current = -1;
- _last = -1;
- } // ByteBufferPool
- public byte[] GetBuffer()
- {
- Object cookie = null;
- try
- {
- // If a ThreadAbortException gets thrown after the exchange,
- // but before the result is assigned to cookie, then the
- // control cookie is lost forever. However, the buffer pool
- // will still function normally and return everybody a new
- // buffer each time (that isn't very likely to happen,
- // so we don't really care).
- cookie = Interlocked.Exchange(ref _controlCookie, null);
- if (cookie != null)
- {
- // we have the control cookie, so take a buffer
- if (_current == -1)
- {
- _controlCookie = cookie;
- // no pooled buffers available
- return new byte[_bufferSize];
- }
- else
- {
- // grab next available buffer
- byte[] buffer = _bufferPool[_current];
- _bufferPool[_current] = null;
- // update "current" index
- if (_current == _last)
- {
- // this is the last free buffer
- _current = -1;
- }
- else
- {
- _current = (_current + 1) % _max;
- }
- _controlCookie = cookie;
- return buffer;
- }
- }
- else
- {
- // we don't have the control cookie, so just create a new buffer since
- // there will probably be a lot of contention anyway.
- return new byte[_bufferSize];
- }
- }
- catch (ThreadAbortException)
- {
- if (cookie != null)
- {
- // This should be rare, so just reset
- // everything to the initial state.
- _current = -1;
- _last = -1;
- // restore cookie
- _controlCookie = cookie;
- }
- throw;
- }
- } // GetBuffer
- public void ReturnBuffer(byte[] buffer)
- {
- if (buffer == null)
- throw new ArgumentNullException("buffer");
- // The purpose of the buffer pool is to try to reduce the
- // amount of garbage generated, so it doesn't matter if
- // the buffer gets tossed out. Since we don't want to
- // take the perf hit of taking a lock, we only return
- // the buffer if we can grab the control cookie.
- Object cookie = null;
- try
- {
- // If a ThreadAbortException gets thrown after the exchange,
- // but before the result is assigned to cookie, then the
- // control cookie is lost forever. However, the buffer pool
- // will still function normally and return everybody a new
- // buffer each time (that isn't very likely to happen,
- // so we don't really care).
- cookie = Interlocked.Exchange(ref _controlCookie, null);
- if (cookie != null)
- {
- if (_current == -1)
- {
- _bufferPool[0] = buffer;
- _current = 0;
- _last = 0;
- }
- else
- {
- int newLast = (_last + 1) % _max;
- if (newLast != _current)
- {
- // the pool isn't full so store this buffer
- _last = newLast;
- _bufferPool[_last] = buffer;
- }
- }
- _controlCookie = cookie;
- }
- }
- catch (ThreadAbortException)
- {
- if (cookie != null)
- {
- // This should be rare, so just reset
- // everything to the initial state.
- _current = -1;
- _last = -1;
- // restore cookie
- _controlCookie = cookie;
- }
- throw;
- }
- } // ReturnBuffer
- } // ByteBufferPool
- } // namespace System.IO
ByteBufferPool.cs
最新推荐文章于 2024-05-15 09:48:00 发布