OSX - передача результатов midiReadProc в основной поток в C

У меня есть следующая структура программы в OSX/Darwin:

Поток-производитель генерирует данные и передает их в кольцевой буфер.

Потребительский поток CoreAudio в реальном времени визуализирует данные из кольцевого буфера в ЦАП.

Они координируются с помощью dispatch_semaphores.

Параметры потока производителя можно контролировать с помощью графического интерфейса пользователя (GLUT, не какао) или MIDI.

Что касается управления производителем из графического интерфейса, все работает очень хорошо.

Однако обратный вызов midiReadProc() «живет» в своем собственном потоке реального времени, из которого поток производителя не должен ни контролироваться, ни уведомляться, но MIDI-данные должны каким-то образом передаваться в вместо этого основной поток, из которого поток производителя должен быть поставлен в очередь и обновлен.

Есть ли способы сделать это, не будучи слишком специфичным для OSX?

Заранее спасибо.


person user3078414    schedule 30.01.2016    source источник


Ответы (2)


Одним из способов сделать это может быть использование циклического FIFO без блокировки для входящих MIDI-данных. Затем поток производителя аудио может опросить этот fifo, прежде чем генерировать следующий пакет данных для потребителя в реальном времени.

person hotpaw2    schedule 30.01.2016
comment
Спасибо. Я бы предпочел держаться как можно дальше от iOS и, если возможно, ближе к обычному UNIX. У меня была утилита озвучивания, которая работала так, как было задумано, пока производящие данные оставались в потоке рендеринга CA. К сожалению, это перегружало поток рендеринга, в то время как 11 других логических ядер оставались практически бездействующими. Как только мне удалось отделить и распараллелить производителя от потока рендеринга, MIDI-ридер, который содержит довольно сложную фильтрацию данных, рано или поздно вылетит из кольцевого буфера, даже если использовать dispatch_async(dispatch_get_main_queue()..) для перемещения соответствующих данных из него. - person user3078414; 30.01.2016
comment
Lock-free потребитель не должен требовать отправки. Как реализовать межплатформенную многопоточность жесткого реального времени в UNIX или Linux (если это вообще возможно) — это совершенно другой вопрос. - person hotpaw2; 30.01.2016
comment
Спасибо. Потребителем (интерпретируемой) MIDI-информации здесь должен быть производитель, который может ожидать dispatch_semaphore_wait, сигнализируемый потоком рендеринга потребителя CA (в реальном времени). На этом этапе я не стремлюсь к строгим требованиям жесткой синхронизации, а скорее пытаюсь найти самое простое решение, в котором обновление нескольких значений из MIDI не должно вызывать повреждение данных или вызывать сбой циклического буфера между производителем (не CA) и потребителем CA. склонный... - person user3078414; 31.01.2016
comment
У потребителя fifo без блокировки не должно быть никаких причин для сбоя. Он должен просто читать из предварительно выделенной памяти. - person hotpaw2; 31.01.2016
comment
Спасибо, что поощряете меня двигаться по правильному пути в правильном направлении! - person user3078414; 31.01.2016
comment
Как вы гарантируете, что поток MIDI может безопасно записывать в кольцевой буфер и не сталкиваться с проблемами параллелизма, не блокируя поток MIDI? Любая переменная синхронизации, записанная потоком MIDI, в конечном итоге должна быть прочитана другим потоком... - person bio; 15.04.2016
comment
Вы не пишете безопасно. Только атомарно. Вы делаете циклический буфер без блокировки достаточно большим, чтобы, если вам нужно синхронизировать, приложение уже не удалось. - person hotpaw2; 15.04.2016

Как я это делаю, я использую кольцевой буфер и копирую эти миди-сообщения в кольцевой буфер в обратном вызове. Затем в основном потоке опросите кольцевой буфер и обработайте данные.

person dave234    schedule 30.01.2016