我们正在使用c ++设计p2p应用程序,它使用UDP将语音传输到其他对等方。
我们在线程中的缓冲区中捕获麦克风信号,该线程在while
循环中捕获语音一秒钟。对于在缓冲区中捕获的每秒语音,将其分组为,将其发送给其他对等方。现在我需要一个适当的数据结构在目的地,以应对实时传输。我将用于屏幕捕获的相同数据结构。以下是使用队列我想到的两种方法
使用链表实现队列,该链表在图像的情况下维护OneSecVoice
个对象或Image
对象的队列。
使用OneSecVoice
或Image
个对象的静态数组实现队列
OneSecVoice/Image
, Image/OneSecVoice
个对象将包含数据包总数,数据包缓冲区。
通过从队列中弹出Image/OneSecVoice
,一个线程将实时持续扫描队列并取出最新完整 Image/OneSecVoice
。
选择哪个使用链接列表实现队列或使用静态数组实现队列。
我和我的朋友正在争吵,所以我们决定在这里发帖。
答案 0 :(得分:4)
我会使用boost::circular_buffer。您将获得具有固定内存区域且没有意外内存分配的缓存优势。
为了达到最大化 效率,circular_buffer存储 它的元素在一个连续的区域 内存,然后启用:
- 使用固定内存而不隐含或 意外的内存分配。
- 快速恒定时间插入和移除 正面和背面的元素。
- 快速恒定时间随机访问 元素。
- 适用于实时和性能关键应用程序。
醇>可能的应用 circular_buffer包括:
- 最近收到的存储 样本,在新样本到达时覆盖最旧的样本。
- 作为潜在的 有界缓冲区的容器(见 有界缓冲区示例)。
- 一种存储指定数量的缓存 最后插入的元素。
- 高效的固定容量FIFO(First In,First Out)或LIFO(后进先出) 删除最旧的队列 (在第一次插入时)元素已满。
答案 1 :(得分:3)
不执行任何一项。使用标准库中预先存在的实现:
std::queue<T, std::list<T> >
std::queue<T, std::deque<T> > // uses deque by default, by the way
你可以输入这些来解决这两个问题非常容易:
template <typename T>
struct queue_list
{
typedef typename std::queue<T, std::list<T> > value_type;
}
template <typename T>
struct queue_array
{
typedef typename std::queue<T, std::deque<T> > value_type;
}
typedef queue_list<the_type>::value_type container_type; // use one
typedef queue_array<the_type>::value_type container_type;
现在简介并找到哪个更好。对于缓存,数组可能会有更好的性能。
您可以使用boost's pool allocator尝试获取列表快速插入和删除的好处,以及数组的缓存性能:
typedef typename std::queue<T, std::list<T, boost::pool_allocator<T> > > value_type;
另一种尝试的结构是boost::circular_buffer
,suggested by fnieto:
template <typename T>
struct queue_buffer
{
typedef typename std::queue<T, boost::circular_buffer<T> > value_type;
}
答案 2 :(得分:1)
如果接收端的唯一操作是从队列中弹出,我真的没有看到使用静态数组的意义,如果你需要对大量的连续数据进行操作或者随机访问。
我认为使用静态数组不会节省任何空间。当然,你是为每个条目保存一个指针,但代价是分配一个大的固定内存块。如果你的队列有时会变得那么大,那么你可能需要链表提供的灵活性,因为它可以增长到任意大小。
如果您想限制它可以增长的大小,您可以在任一方案中执行此操作。
答案 3 :(得分:0)
链接列表将是规范方法,“使用静态数组实现队列”实际上是我如何去做 - 以便重新组装udp数据包,然后可能将顺序数据传递给LL,以便它被命令。你怎么跳舞“连续扫描队列并取出最新的完整”,因为你不能把它塞进去,因为udp可能会出现意料之外的顺序。最新完成并不意味着“咖啡”出现在“豆类型”之后,所以你可以在那里找到一些混淆的咖啡豆。