【发布时间】:2012-07-22 03:03:11
【问题描述】:
我有一个产生数据流的仪器;我的代码通过回调onDataAcquisitionEvent(const InstrumentOutput &data) 访问这些数据。数据处理算法可能比数据到达的速度慢得多,所以我不能希望处理每一条数据(我也不必),但希望处理尽可能多的数据。感谢仪器作为环境传感器,具有我无法控制的数据采集速率。例如,InstrumentOutput 可以是一个包含不同位置的三个同时压力测量值的类。
我还需要保留一些简短的数据历史记录。例如,假设我可以合理地希望每 200 毫秒左右处理一次数据样本。大多数时候,我很乐意只处理最后一个样本,但有时我需要查看在最新样本之前到达的几秒钟的数据,这取决于最后一个样本中是否存在异常读数。
另一个要求是尽快退出onDataAcquisitionEvent()回调,避免传感器数据丢失。
数据采集库(第三方)在单独的线程上收集仪器数据。
我想到了以下设计;拥有单个生产者/单个消费者队列,并在 onDataAcquisitionEvent() 回调中将数据令牌推送到同步队列中。
在接收端,有一个循环从队列中弹出数据。由于数据到达率很高,循环几乎永远不会休眠。在每次迭代中,都会发生以下情况:
- 从队列中弹出所有可用数据,
- 弹出的数据被复制到一个循环缓冲区中(我使用了 boost 循环缓冲区),这样一些历史记录总是可用的,
- 处理缓冲区中的最后一个元素(并可能查看之前的元素),
- 重复循环。
问题:
- 这种设计是否合理,有哪些缺陷?和
- 还有什么更好的设计?
编辑:我想到的一个问题是当循环缓冲区的大小不足以容纳所需的历史时;目前我只是重新分配循环缓冲区,使其大小加倍。我希望我只需要这样做一两次。
【问题讨论】:
-
请说得更具体一点:当您写“数据”时,您是指实际的 PCM 样本还是某种事件,例如MIDI 事件?
-
谢谢,“乐器”与音乐无关,它是一个环境传感器。我会更新原帖。
标签: c++ buffering circular-buffer data-acquisition