C ++:具有多个元素的高效获取/放置的队列?

时间:2011-03-28 21:32:49

标签: c++ stl queue

所以,我觉得在C ++中应该有一个很好的内置解决方案,但我不确定它是什么。

我需要一个队列(理想情况下是线程安全的,但如果需要的话,我可以自己将它包装起来),它可以有效地处理字节组 - 允许不同大小的读/写。

所以,界面看起来像是

//removes the first bytesToRead elements from the front of the queue and places them in array; returns the actual number of bytes dequeued
int dequeue(unsigned char *array, int bytesToRead) 
//Adds bytesToWrite elements from array to the end of the queue; does nothing and returns 0 if this would exceed the queue's max size
int enqueue(unsigned char *array, int bytesToWrite)

我可以自己写一个没有太多困难,但似乎这应该是很容易就能完成的东西。

STL中最好的东西看起来可能是一个stringbuf - 我必须手动调用sgetc / pubseekoff,但看起来它会起作用。

我希望将此作为当前队列实现的替代品,这是一个性能问题;在此实现中读取的是队列中数据量的O(N)。 (这是一个非常天真的实现 - 每个dequeue都会导致队列中剩余数据的数组副本。)

附加要求(如果需要,我可以在包装器中实现这些要求): - 我需要能够指定缓冲区的最大大小 - 如果可用数据少于请求数据,则读取操作应检索所有可用数据 如果请求的写入超过最大大小并返回失败指示符,则写操作不应执行任何操作

所以,我的问题: 1)stringbuf是否足够?假设不需要调整大小,读/写操作O(1)是否相对于缓冲区中的数据量? (显然,它们可能是所请求项目数量的O(n)。)

2)还有其他一些我认为不足以满足的课程吗?

提前致谢!

4 个答案:

答案 0 :(得分:8)

嗯......你有没有试过这个显而易见的事情:

class queue { 
      std::deque<unsigned char> data;
public:
    int enqueue(unsigned char *array, int bytesToWrite) { 
        data.insert(data.end(), array, array+bytesToWrite);
    }

    int dequeue(unsigned char *array, int bytesToRead) { 
        std::copy(data.begin(), data.begin()+bytesToRead, array);
        // or, for C++11: std::copy_n(data.begin(), bytesToRead, array);

        data.erase(data.begin(), data.begin()+bytesToRead);
    }
};

对不起,我现在感觉不够雄心勃勃,无法添加锁定和你要求的返回值,但两者都不应该非常困难。但是,我没有摆弄你的返回值,而是更改接口以使用迭代器(或者,如果你真的坚持,则引用向量)。

保证插入/移除的元素数量是线性的。

答案 1 :(得分:1)

如果你想要一个非常快速有效的实现,我会选择一个简单的循环缓冲区实现,这意味着你可以在一个或两个副本中进行读取(取决于你是否包装缓冲区的结尾/开头) 。这允许你使用memcpy,根据我的经验,它几乎总是通过大量元素循环执行你的复制。

如果表现不那么重要,我会选择Jerry的答案。

答案 2 :(得分:0)

您可以使用std::stringstream使用write进入队列并使用read弹出队列吗?

答案 3 :(得分:0)

根据建议,std::stringstream可能是最简单,最好的解决方案。

另一个替代方案是std::deque,它将为您提供所需的效率(从队列的任何一端进行所有读/写的常量摊销,并且如果容量是,则通常远小于重新分配的O(N)累)。唯一的缺点是std::deque不支持指针运算(因为所有元素不一定是连续的(在块中)),所以你将无法进行块读/写操作,你将不得不迭代,如下:

std::deque<unsigned char> buf;

int dequeue(unsigned char *array, int bytesToRead) {
  int result = std::min(bytesToRead, buf.size());
  std::copy(buf.begin(), buf.begin() + result, array);
  buf.erase(buf.begin(), buf.begin() + result);
  return result;
}; 

int enqueue(unsigned char *array, int bytesToWrite) {
  buf.insert(buf.end(), array, array + bytesToWrite);
  return bytesToWrite;
};

如果达到最大容量,您应该检查后一个实现,并因此调整结果值。