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

发布于 2024-08-17 07:09:17 字数 991 浏览 6 评论 0原文

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

这是获取 16 位数据缓冲区并将其添加到双端队列的函数

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 调用搞乱了事情,我可以删除它,事情就会再次开始。

更新:我发现了问题,我重构了代码并错过了一个常量,因此出队总是检查为满,导致循环=(

I've got a wrapper around a std::deque that I'm using to queue up audio data (coming in blocks via libavcodec, if that matters).

This is the function that takes a buffer of 16-bit data and adds it to the 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));
  }
}

Definitions of lock/unlock:

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

My problem is, when the data_buffer_.insert statement is included in the code, the thread this function is in will execute once and then lockup. If I remove the code, it works. I tried replace the insert with a manual iteration of the src data, calling push_back() for each element, and this too causes the thread to lock.

Is this a valid way to append data to a deque? I tried it in a test program and it seemed to work fine, and the documentation seems to imply that it's OK. Why would this cause my thread to die?

Updated info: Added error messages for when locking/unlocking fail, and they both succeed just fine. I instrumented them to verify they're being executed in pairs, and they are. It's got to be something with the deque::insert call that's messing things up, I can remove it and things get moving again.

Update: I found the problem, I refactored the code and missed a constant so the dequeue was always checking as full, causing a loop =(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一场信仰旅途 2024-08-24 07:09:17

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

锁定的根源可能在于锁定本身。对 data_buffer_ 的所有访问都应该同步(读和写),包括对 data_buffer_.size() 的调用。如果一个线程从 data_buffer_ 读取数据,而另一个线程向其中写入数据,则可能会出现随机的、未定义的行为。

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

查看更新后的代码,您还应该同步对 pts_values_ 的访问。

That method of inserting into a deque is perfectly valid.

The source of your lockup is likely in the locking itself. All accesses to data_buffer_ should be synchronized (both read and write), including the call to data_buffer_.size(). If one thread reads from data_buffer_ while another thread writes to it, you can get random, undefined behavior.

If, after fixing that, it is still locking up, look for mismatched lock()/unlock() pairs or deadlocks. I'm also assuming you are using atomic locks.

Looking at your updated code, you should also synchronize accesses to pts_values_.

夢归不見 2024-08-24 07:09:17

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

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

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

Since STL usage is fine as shown, I would suggest looking closer at the synchronization. The SDL mutex functions return -1 on error. Put a check for that into the lock() and unlock() and raise an exception, for example. You can log a thread ID on the entry into those functions too.

I'd also check that the input values are correct - make num does not overrun the input buffer.

A plug for good C++ techniques - get into habit of using RAII for lock management. This is what C++ destructors were invented for :)

秋凉 2024-08-24 07:09:17

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

哎呀 - 那里有一个锁。我的猜测是锁不起作用或者读取器没有锁定

读取器线程也锁定吗?你确定锁真的锁住了吗?

sounds like you need some thread locking. If another thread is reading (and hence updating) from the queue then you gotta lock it

oops - there is a lock there. My guess is that the lock is not working or that the reader is not locking

Does the reader thread lock too? Are you sure the lock is actually locking?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文