基于数组的有界缓冲区中的空元素

时间:2012-03-01 13:52:22

标签: c++ data-structures

我有一个经典的生产者/消费者问题。生产者的代码是:

#define BUFFER_SIZE 10
while (true) {
  /* Produce an item */
  while (( (in + 1) % BUFFER_SIZE)  == out)
  ;   /* do nothing -- no free buffers */
  buffer[in] = item;
  in = (in + 1) % BUFFER_SIZE;
}

消费者是:

while (true) {
  while (in == out)
  ; // do nothing -- nothing to consume

  // remove an item from the buffer
  item = buffer[out];
  out = (out + 1) % BUFFER_SIZE;
  return item;
}

这很好但问题是当前八个元素被填满in=9out=0时,生产者就坐在那里并且没有填充最后一个(第九个)元素。如果说in=4out=5,也会发生这种情况。在每种情况下,即使一个插槽仍为空,一个元素仍为空,并且队列看起来是“满的”。

我可以提出一些复杂的检查,但我需要知道是否有一个干净的解决方案来填充整个队列。我尝试先增加,然后放入item,但也会遇到类似的问题。 (-1in的{​​{1}}初始化也不起作用。

2 个答案:

答案 0 :(得分:1)

有关此主题的信息,请参阅Wikipedia。最简单的解决方案似乎是:

  • 始终将一个插槽留空:如果in == out则缓冲区为空; if in == out - 1,缓冲区已满
  • out替换为num_unread_items;执行简单的数学运算,从outnum_unread_items
  • 检索in

...但是还有其他与计算读数和数量相关的选项。写操作(在单独的变量中或直接在inout);或跟踪当前inout之外的最后一次操作是读取还是写入,这允许您消除缓冲区满/缓冲区空案例的歧义。

答案 1 :(得分:1)

在大学的操作系统开发课程中,我有一位兼职教师声称不可能拥有一个只能使用缓冲区中所有N个元素的纯软件解决方案。 我证明他错了我决定称之为赛道解决方案(受到我喜欢跑道的启发)。

在赛道上,您不仅限于400米比赛;比赛可以包括一圈以上。如果两个跑步者是颈部和颈部会发生什么 在比赛中?你怎么知道他们是否被束缚,或者一个跑步者是否已经打了另一个?答案很简单:在比赛中,我们不监控跑步者的位置 在轨道上;我们监控每个跑步者所经过的距离。因此,当两个跑步者是颈部和颈部时,我们可以在一个领带和一个跑步者之间消除歧义 把对方舔了一下。

因此,我们的算法有一个N元素数组,并管理一个2N竞赛。在他们完成各自的2N比赛之前,我们不会重新启动生产者/消费者的计数器。 我们不允许生产者超过消费者超过一圈,我们不允许消费者领先于生产者。 实际上,我们只需要监控生产者和消费者之间的距离。

代码如下:

Item track[LAP];
int consIdx = 0;
int prodIdx = 0;

void consumer()
{ while(true)
  { int diff = abs(prodIdx - consIdx);
    if(0 < diff) //If the consumer isn't tied
    { track[consIdx%LAP] = null;
      prodIdx = (prodIdx + 1) % (2*LAP);
    }
  }
}

void producer()
{ while(true)
  { int diff = (prodIdx - consIdx);
    if(diff < LAP) //If prod hasn't lapped cons
    { track[prodIdx%LAP] = Item();      //Advance on the 1-lap track.
      prodIdx = (prodIdx + 1) % (2*LAP);//Advance in the 2-lap race.
    }
  }
}

自从我最初解决问题以来已经有一段时间了,所以这是根据我最好的回忆。希望我没有忽视任何错误。 希望这有帮助!