对线程安全无阻塞缓冲区管理器的建议
我创建了一个简单的缓冲区管理器类,用于异步套接字。这将防止内存碎片并提高性能。任何关于进一步改进或其他方法的建议?对安全" title="线程安全">线程安全无阻塞缓冲区管理器的建议
public class BufferManager {
private int[] free;
private byte[] buffer;
private readonly int blocksize;
public BufferManager(int count, int blocksize)
{
buffer = new byte[count * blocksize];
free = new int[count];
this.blocksize = blocksize;
for (int i = 0; i < count; i++)
free[i] = 1;
}
public void SetBuffer(SocketAsyncEventArgs args)
{
for (int i = 0; i < free.Length; i++)
{
if (1 == Interlocked.CompareExchange(ref free[i], 0, 1))
{
args.SetBuffer(buffer, i * blocksize, blocksize);
return;
}
}
args.SetBuffer(new byte[blocksize], 0, blocksize);
}
public void FreeBuffer(SocketAsyncEventArgs args)
{
int offset = args.Offset;
byte[] buff = args.Buffer;
args.SetBuffer(null, 0, 0);
if (buffer == buff)
free[offset/blocksize] = 1;
}
}
回答:
编辑:
下一部开拓创新的答案解决过于紧密耦合的代码结构问题。但是,考虑到整个解决方案,我会避免只使用一个大缓冲区,并以这种方式移交它的片段。你将你的代码暴露在缓冲区溢出(我们应该把它称为缓冲区“underrun”问题)。相反,我会管理一个字节数组,每个数组都是一个离散的缓冲区。移交的偏移总是0,大小始终是缓冲区的长度。任何试图读取/写入超出边界的错误代码都会被捕获。
原来的答复
你加上的类的SocketAsyncEventArgs那里其实它所需要的是分配缓冲区的函数,改变SetBuffer到: -
public void SetBuffer(Action<byte[], int, int> fnSet) {
for (int i = 0; i < free.Length; i++)
{
if (1 == Interlocked.CompareExchange(ref free[i], 0, 1))
{
fnSet(buffer, i * blocksize, blocksize);
return;
}
}
fnSet(new byte[blocksize], 0, blocksize);
}
现在你可以调用从消费类似这样的代码: -
myMgr.SetBuffer((buf, offset, size) => myArgs.SetBuffer(buf, offset, size));
我不确定该类型推理是否足够聪明resolv e这种情况下的buf, offset, size
的类型。如果没有,你将不得不放置类型参数列表: -
myMgr.SetBuffer((byte[] buf, int offset, int size) => myArgs.SetBuffer(buf, offset, size));
但是现在你的类可用于分配缓冲区的要求,所有的方式也使用字节[],INT,INT模式这很常见。
当然,你需要去耦自由操作但那是: -
public void FreeBuffer(byte[] buff, int offset) {
if (buffer == buff)
free[offset/blocksize] = 1;
}
这需要你在消费的情况下,代码SocketAsyncEventArgs
调用SetBuffer上的EventArgs。如果您担心这种方法会减少释放缓冲区并将其从套接字中删除的原子性,那么将此调整后的缓冲区管理器子类化,并在子类中包含特定的代码。
回答:
我用完全不同的方法创建了一个新类。
我有一个接收字节数组的服务器类。然后它会调用不同的委托给它们缓冲对象,以便其他类可以处理它们。当这些类完成时,他们需要一种将缓冲区推回堆栈的方法。
public class SafeBuffer {
private static Stack bufferStack;
private static byte[][] buffers;
private byte[] buffer;
private int offset, lenght;
private SafeBuffer(byte[] buffer)
{
this.buffer = buffer;
offset = 0;
lenght = buffer.Length;
}
public static void Init(int count, int blocksize)
{
bufferStack = Stack.Synchronized(new Stack());
buffers = new byte[count][];
for (int i = 0; i < buffers.Length; i++)
buffers[i] = new byte[blocksize];
for (int i = 0; i < buffers.Length; i++)
bufferStack.Push(new SafeBuffer(buffers[i]));
}
public static SafeBuffer Get()
{
return (SafeBuffer)bufferStack.Pop();
}
public void Close()
{
bufferStack.Push(this);
}
public byte[] Buffer
{
get
{
return buffer;
}
}
public int Offset
{
get
{
return offset;
}
set
{
offset = value;
}
}
public int Lenght
{
get
{
return buffer.Length;
}
}
}
以上是 对线程安全无阻塞缓冲区管理器的建议 的全部内容, 来源链接: utcz.com/qa/258359.html