将元素块添加到std :: deque的末尾

时间:2010-01-13 01:49:42

标签: c++ deque

我有一个围绕std :: deque的包装器,我正在使用它来排队音频数据(通过libavcodec进入块,如果这很重要的话)。

这是一个获取16位数据缓冲区并将其添加到deque

的函数
void AVAudioBuffer::enqueue(int16_t* src, size_t num, double pts) {
  // Save current size of buffer
  size_t size = data_buffer_.size();

  lock();
  data_buffer_.insert(data_buffer_.end(), src, src+num);
  unlock();

 // Push PTS value onto queue
 if (pts != AV_NOPTS_VALUE) {
   pts_values_.push_back(pair<int,double>(size, pts));
  }
}

锁定/解锁的定义:

void   lock()     { SDL_mutexP(mute_access_);     }
void unlock()     { SDL_mutexV(mute_access_);     }

我的问题是,当代码中包含data_buffer_.insert语句时,此函数所在的线程将执行一次然后锁定。如果我删除代码,它的工作原理。我尝试用src数据的手动迭代替换插入,为每个元素调用push_back(),这也导致线程锁定。

这是将数据附加到双端队列的有效方法吗?我在一个测试程序中尝试过它似乎工作正常,文档似乎暗示它没关系。为什么这会导致我的线程死亡?

更新信息:添加了锁定/解锁失败时的错误消息,它们都成功了。我指示他们验证他们是成对执行的,他们是。它必须是deque :: insert调用的东西搞砸了,我可以删除它,事情再次发生变化。

更新:我发现了问题,我重构了代码并错过了一个常量,所以dequeue总是检查为full,导致循环=(

3 个答案:

答案 0 :(得分:1)

插入双端队列的方法完全有效。

锁定的来源很可能是锁定本身。对data_buffer_的所有访问都应该同步(读取和写入),包括对data_buffer_.size()的调用。如果一个线程从data_buffer_读取而另一个线程写入它,则可以获得随机的,未定义的行为。

如果在修复之后仍然锁定,请查找不匹配的lock()/ unlock()对或死锁。我还假设你正在使用原子锁。

查看更新后的代码,还应该同步访问pts_values _。

答案 1 :(得分:1)

由于如图所示STL使用情况良好,我建议仔细研究同步。 SDL互斥锁函数在出错时返回-1。例如,检查一下lock()unlock()并引发异常。您也可以将条目上的线程ID记录到这些函数中。

我还要检查输入值是否正确 - make num不会超出输入缓冲区。

用于良好C ++技术的插件 - 养成使用RAII进行锁管理的习惯。这就是C ++析构函数的发明:)

答案 2 :(得分:0)

听起来你需要一些线程锁定。如果另一个线程正在从队列中读取(并因此更新),那么你必须将其锁定

哎呀 - 那里有锁。我的猜测是锁没有工作或读者没有锁定

读者线程也锁定了吗?你确定锁实际上是锁定的吗?