mangos 之 CircularBuffer
循环缓冲区是应用比较广泛的数据结构了,mangos也用到了,但是mangos中的CircularBuffer有点不一样,就是其内部将用户指定的缓冲区大小double了一下,而往缓冲区中添加数据的函数也有点小区别,看看代码先:
bool CircularBuffer::Write(const char *s,size_t l)
{
if (m_q + l > m_max)
{
m_owner.Handler().LogError(&m_owner, "CircularBuffer::Write", -1, "write buffer overflow");
return false; // overflow
}
m_count += (unsigned long)l;
if (m_t + l > m_max) // block crosses circular border
{
size_t l1 = m_max - m_t; // size left until circular border crossing
// always copy full block to buffer(buf) + top pointer(m_t)
// because we have doubled the buffer size for performance reasons
memcpy(buf + m_t, s, l); //////////////////////(A)
memcpy(buf, s + l1, l - l1);
m_t = l - l1;
m_q += l;
}
else
{
memcpy(buf + m_t, s, l); /////(B1)
memcpy(buf + m_max + m_t, s, l); //////////////////(B)
m_t += l;
if (m_t >= m_max)
m_t -= m_max;
m_q += l;
}
return true;
}
在(A)的地方,没有memcpy l1的长度,而是l长度,即s中的后l-l1个字节拷贝到了缓冲区的后半部分去。
在(B)处本来可以调用一次memcpy(即B1)就可以搞定的,还又调用了一次B,将数据写到缓冲区后半部分对应的区域。
一开始没有理解怎么回事,这不是画蛇添足么。后来发现mangos的CircularBuffer类还提供了几个函数:GetStart,SoftRead和Remove,他们就是让用户直接操控循环缓冲区指针的接口。用户不可能处理CircularBuffer跨越边界的问题,所有用户看到的都是连续的区域。通过上面A,B的处理,即使发生跨越边界的点,用户也可以取到正确的数据。这种方式不错,呵呵!
另外,codeproject上有个BipBuffer也是类似的(),需要向用户提供连续空间的指针,它是通过划分区域来实现的,分配的时候就直接分配连续的空间,避免了分段的发生。BipBuffer值负责管理缓冲区,即它只负责给你一块空间(Reserve),你自己写,写好了告诉它(Commit)。这种方式可能会在某些时刻浪费一部分缓冲区空间,即用潜在的空间浪费换取连续空间。
阅读(1432) | 评论(0) | 转发(0) |