我正在研究的软件是带有滑动窗口的数据分析器。我有2个线程,一个生产者和一个消费者,它们使用循环缓冲区。
只有当缓冲区中的第一个元素足够大时,消费者才必须处理数据,因此缓冲区中至少有X个元素。但是在处理之后,由于移动窗口,只能删除X / 4数据。
我的解决方案效果很好,除了我在快速(忙于等待检查)或有效(睡眠一段时间)之间进行权衡。问题是睡眠时间根据负载,线程调度和细化复杂性而变化,因此我可能会降低性能。
有没有办法轮询信号量以检查是否至少有X个元素,否则阻塞线程,但在处理完成后只获取X / 4? tryAcquire选项不起作用,因为当它唤醒时,线程会消耗所有数据,而不是一半。
我考虑过在第二个缓冲区中复制元素,但实际上有7个大数据循环缓冲区,因此我想避免数据重复,甚至数据移动。
//common structs
QSemaphore written;
QSemaphore free;
int writtenIndex = 0;
int readIndex = 0;
myCircularBuffer buf;
bool scan = true;
//producer
void produceData(data d)
{
while ( free.tryAcquire(1, 1000) == false && scan == true)
{
//avoid deadlock!
//once per second give up waiting and check if closing
}
if (scan == false) return;
buf.at(writtenIndex) = d;
writtenIndex = (writtenIndex+1) % bufferSize;
written.release();
}
//consumer
void consumeData()
{
while(1)
{
//here goes the problem: usleep (slow), sched_yield (B.F.O.W.) or what?
if (buf.at(writtenIndex).age - buf.at(readIndex).age < X)
{
//usleep(100); ? how much time?
//sched_yield(); ?
//tryAcquire not an option!
continue;
}
processTheData();
written.acquire(X/4);
readIndex = (readIndex + X/4) % bufferSize;
free.release(X/4);
}