Добавление блока элементов в конец std :: deque - PullRequest
2 голосов
/ 13 января 2010

У меня есть обертка вокруг 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? Я попробовал это в тестовой программе, и это, казалось, работало нормально, и документация, кажется, подразумевает, что это в порядке. Почему это привело к смерти моей нити?

Обновлена ​​информация: добавлены сообщения об ошибках, когда блокировка / разблокировка не удалась, и оба они успешно выполняются. Я поручил им проверить, что они выполняются парами, и они есть. Это должно быть что-то с вызовом deque :: insert, который запутывает вещи, я могу удалить это, и все снова начинает двигаться.

Обновление: я обнаружил проблему, реорганизовал код и пропустил константу, поэтому очередь всегда проверялась как полная, вызывая цикл = (

Ответы [ 3 ]

1 голос
/ 13 января 2010

Этот метод вставки в deque совершенно действителен.

Источник вашей блокировки, вероятно, находится в самой блокировке.Все обращения к data_buffer_ должны быть синхронизированы (как чтение, так и запись), включая вызов data_buffer_.size ().Если один поток читает данные из data_buffer_, в то время как другой поток пишет в него, вы можете получить случайное, неопределенное поведение.

Если после исправления это все еще блокируется, ищите несовпадающие пары lock () / unlock ()или тупики.Я также предполагаю, что вы используете атомарные блокировки.

Глядя на ваш обновленный код, вы также должны синхронизировать доступ к pts_values ​​_.

1 голос
/ 13 января 2010

Так как использование STL в порядке, как показано, я бы посоветовал присмотреться к синхронизации. Функции мьютекса SDL возвращают -1 в случае ошибки. Поставьте проверку для этого в lock() и unlock() и, например, вызовите исключение. Вы также можете зарегистрировать идентификатор потока в записи в этих функциях.

Я бы также проверил правильность входных значений - make num не переполняет входной буфер.

Плагин для хороших методов C ++ - привыкните использовать RAII для управления блокировками. Это то, для чего были изобретены деструкторы C ++:)

0 голосов
/ 13 января 2010

звучит так, как будто вам нужна блокировка потока. Если другой поток читает (и, следовательно, обновляет) из очереди, вам нужно заблокировать его

упс - там есть замок. Я предполагаю, что блокировка не работает или что считыватель не блокирует

Читатель тоже блокирует поток? Вы уверены, что замок на самом деле блокируется?

...