Задание № 1901

Студент

Мельников Сергей

Задача

Очередь аудио-сэмплов

Состояние

Завершено

Баллов

5

Назначено

02.12.2019, 14:45

Завершено

22.01.2020, 09:32

Разработать класс, позволяющий производить многопоточное буферизированное чтение данных. Данные читаются/пишутся наборами блоков фиксированного размера. Количество блоков в наборе - произвольное. Типичный пример подобных данных - последовательность аудио-сэмплов одинакового (небольшого, 1-8 байт) размера.

Постановка задачи

Задание предполагает одновременную работу двух потоков выполнения: один поток (поток-читатель) считывает данные в очередь, второй (поток-писатель) - с некоторой периодичностью проверяет очередь, выбирает из неё очередные данные, и записывает их в файлы.

Очередь выполняет здесь роль регулятора, который:

  • позволяет согласовать скорости чтения и записи данных между потоками,
  • гарантирует порядок и целостность передаваемых данных.
  • синхронизирует доступ к данным из разных потоков выполнения.

Класс очереди должен быть спроектирован в рамках концепции RAII, и являться владельцем буфера данных. Класс очереди реализует внутри себя кольцевой буфер данных.

Примерный прототип класса очереди:

class SampleFIFO {
   SampleFIFO(size_t blockSize, size_t maxBlocks);
   ~SampleFIFO();
   void * getFree(size_t count);
   void addReady(void * data);
   void * getReady(size_t & count);
   void addFree(void * data);
};
  • SampleFIFO(blockSize, maxBlocks) - выделяет буфер данных, с заданным размером блока, и с фиксированным количеством блоков.
  • ~SampleFIFO() - деструктор, освобождает память.
  • getFree(count) - метод, вызываемый потоком-писателе, для проверки наличия count смежных свободных блоков для записи данных. Если требуемое количество смежных свободных блоков найдено, то функция возвращает указатель на первый свободный блок, в противном случае функция возвращает null.
  • addReady(data) - метод, вызываемый потоком-писателем, помечающий, что запрошенные ранее блоки заполнен и готов к передаче.
  • getReady(&count) - метод, вызываемый потоком-читателем, для проверки наличия count готовых для чтения смежных блоков данных. Если требуемое количество готовых смежных блоков найдено, то функция возвращает указатель на первый готовый блок, в противном случае функция возвращает null. Функция может вернуть не null и в том случае, когда имеется менее чем count готовых смежных блоков, в этой ситуации функция через входной аргумент count возвращает реальное количество готовых блоков.
  • addFree(data) - метод, вызываемый потоком-читателем, помечающий, что выданные ранее ранее блоки, освобождёны и могут повторно использоваться очередью.

Тестирование

Необходимо реализовать ряд тестов в порядке усложнения:

  • в каждом тесте на вход очереди подаются наборы из разного количества блоков данных (например 16-битные сэмплы из wav файла, считанного в бинарном режиме), а на выходе - эти данные накапливаются (например сохраняются на диск в бинарном режиме, как wav файл), и по окончании передачи проводится побайтовая сверка соответствующих блоков.
  • для базовой проверки функционала обязателен однопоточный тест, поочерёдное чтение/запись в одном потоке.
  • также необходим многопоточный тест, где чтение/запись производятся из разных потоков.

Дополнительный бал за тест на "необычные" модели поведения потоков читателя и писателя:

  • тест на переполнение очереди потоком-писателем.
  • писатель много раз вызывает getFree(), затем заполняет данные, а затем в произвольном порядке помечает блоки как готовые вызовами addReady().
  • тест на опустошении очереди потоком-читателем.
  • читатель много раз вызывает getReady(), сохраняет данные, а затем в произвольном порядке помечает блоки как свободные вызовами addFree().

Действия