我正在使用std :: queue来缓冲网络上的消息(在这种情况下是CAN总线)。在中断期间,我将消息添加到"收件箱"。然后我的主程序检查每个循环,如果队列是空的,如果不处理消息。问题是,队列弹出直到空(它从while (! inbox.empty())
退出,但是下次我将数据推送到它时,它正常工作但旧数据仍然在后面停留。< / p>
例如,第一条消息推送&#34; 1&#34;到队列。循环读取
下一条消息是&#34; 2&#34;。下一步是
如果我在另一次阅读之前收到两条消息,&#34; 3&#34;,&#34; 4&#34;,那么下次阅读将是
我很困惑。我也在使用STM32F0 ARM芯片并在线进行mbed,并且不知道这是否在硬件上运行不佳或者是什么!
我担心线程安全,所以我添加了一个额外的缓冲队列,只有当它解锁时才会推送到收件箱。#34;。一旦我跑了这个,我还没有看到任何冲突发生!
Pusher代码:
if (bInboxUnlocked) {
while (! inboxBuffer.empty()) {
inbox.push (inboxBuffer.front());
inboxBuffer.pop();
}
inbox.push(msg);
} else {
inboxBuffer.push(msg);
printf("LOCKED!");
}
主程序读取代码
bInboxUnlocked = 0;
while (! inbox.empty()) {
printf("%d\r\n", inbox.front().data);
inbox.pop();
}
bInboxUnlocked = 1;
有人想到吗?我用错了吗?还有其他方法可以轻松完成我正在做的事情吗?我希望缓冲区足够小,可以实现一个小圆形数组,但是手头有队列,我希望不必这样做。
答案 0 :(得分:1)
基于我从基本的谷歌搜索中可以得出的结论,你的CPU本质上是一个单核CPU。如果是这样,那么在这里不应该有任何内存屏障问题需要处理。
另一方面,如果你有多个CPU内核需要处理,那么有必要在关键位置填写显式围栏,或者使用像std :: mutex这样的C ++ 11类,为你照顾这个。
但是如果你能保证:
,那么使用单个CPU的原始用例,并且没有内存防护问题。A)在排队之前,队列中的中断处理代码预计会缓冲的消息数有一定的上限,并且:
B)您正在缓冲的消息是PODs
然后,值得探索的std::queue
的潜在替代方法是滚动您自己的简单队列,只使用静态std::array
,或者std::vector
,{{1}头指针和int
尾指针。谷歌搜索应该找到很多实现这个简单算法的例子:
拉拔器检查“if head!= tail”,如果是,则读取int
中的消息并递增头部。增量意味着:head =(head + 1)%queuesize。拉出器检查递增queue[head]
(也是模数队列化)是否导致tail
,如果是,则队列已填满(根据此方法的先决条件,不应发生这种情况)。如果没有,将消息放入队列[tail],并增加尾部。
如果所有这些操作都按照正确的顺序完成,那么净效应与使用head
相同,但是:
1)没有std::queue
的开销和它使用的堆分配。应该是嵌入式平台的重大胜利。
2)由于队列是一个向量,在连续的内存中,这应该利用CPU缓存(通常就是这种情况,使用传统的CPU)。