Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 什么';CoreAudio实时线程与UI线程通信的正确方法是什么?_Macos_Cocoa_Core Audio - Fatal编程技术网

Macos 什么';CoreAudio实时线程与UI线程通信的正确方法是什么?

Macos 什么';CoreAudio实时线程与UI线程通信的正确方法是什么?,macos,cocoa,core-audio,Macos,Cocoa,Core Audio,我需要在CoreAudio的实时线程和UI线程之间传递数据(单向,RT->UI)。我知道我不能使用任何Cocoa/Objective C方法,如performSelectorOnMainThread或NSNotification,也不能使用任何分配内存的方法,因为这可能会阻塞RT线程 线程之间通信的正确方法是什么?我可以使用GCD消息队列还是有更基本的系统可以使用 编辑: 再仔细考虑一下,我想我可以使用一个无锁的环形缓冲区,RT线程将消息放入其中,UI线程检查要拉出的消息。这是最好的方法吗?如果

我需要在CoreAudio的实时线程和UI线程之间传递数据(单向,RT->UI)。我知道我不能使用任何Cocoa/Objective C方法,如
performSelectorOnMainThread
NSNotification
,也不能使用任何分配内存的方法,因为这可能会阻塞RT线程

线程之间通信的正确方法是什么?我可以使用GCD消息队列还是有更基本的系统可以使用

编辑:


再仔细考虑一下,我想我可以使用一个无锁的环形缓冲区,RT线程将消息放入其中,UI线程检查要拉出的消息。这是最好的方法吗?如果是的话,是否已经有一个系统可以在CoreAudio或其他地方实现这一点,或者我需要自己编写代码吗?

事实证明,这比我预期的要简单得多,我提出的解决方案只是使用Portaudio环缓冲区。我需要将pa_ringbuffer.[ch]和pa_memorybarrier.h添加到我的项目中,然后定义一个MessageData结构来存储在环形缓冲区中

typedef struct MessageData {
    MessageType type;
    union {
        struct {
            NSUInteger position;
        } position;
    } data;
} MessageData;
_playbackData->RTToMainBuffer = malloc(sizeof(MessageData) * 32);
PaUtil_InitializeRingBuffer(&_playbackData->RTToMainRB, sizeof(MessageData),
                            32, _playbackData->RTToMainBuffer);
然后我分配了一些空间来存储32条消息,并创建了环形缓冲区

typedef struct MessageData {
    MessageType type;
    union {
        struct {
            NSUInteger position;
        } position;
    } data;
} MessageData;
_playbackData->RTToMainBuffer = malloc(sizeof(MessageData) * 32);
PaUtil_InitializeRingBuffer(&_playbackData->RTToMainRB, sizeof(MessageData),
                            32, _playbackData->RTToMainBuffer);
最后,我每20毫秒启动一次NSTimer,从环形缓冲区中提取数据

while (PaUtil_GetRingBufferReadAvailable(&_playbackData->RTToMainRB)) {
    MessageData *dataPtr1, *dataPtr2;
    ring_buffer_size_t sizePtr1, sizePtr2;

    // Should we read more than one at a time?
    if (PaUtil_GetRingBufferReadRegions(&_playbackData->RTToMainRB, 1,
                                        (void *)&dataPtr1, &sizePtr1,
                                        (void *)&dataPtr2, &sizePtr2) != 1) {
        continue;
    }

    // Parse message
    switch (dataPtr1->type) {
        case MessageTypeEOS:
            break;

        case MessageTypePosition:
            break;

        default:
            break;
    }
    PaUtil_AdvanceRingBufferReadIndex(&_playbackData->RTToMainRB, 1);
}
然后在实时线程中,将消息推送到ringbuffer很简单

MessageData *dataPtr1, *dataPtr2;
ring_buffer_size_t sizePtr1, sizePtr2;

if (PaUtil_GetRingBufferWriteRegions(&data->RTToMainRB, 1,
                                     (void *)&dataPtr1, &sizePtr1,
                                     (void *)&dataPtr2, &sizePtr2)) {
    dataPtr1->type = MessageTypePosition;
    dataPtr1->data.position.position = currentPosition;

    PaUtil_AdvanceRingBufferWriteIndex(&data->RTToMainRB, 1);
} 

环形缓冲区是一个很好的解决方案。如果您需要双向通信,即收件箱/发件箱消息传递,请选择两种方式

如果您不想使用Portaudio,这是iOS/Mac的一个很好的实现


我使用环形缓冲区,用原子C数据类型作为标志,并声明它们是易失的。帧速率或较慢的计时器在UI端轮询它们。这是你自己的密码,谢谢。做了更多的研究后,我发现Ross Bencina建议使用Portaudio队列作为起点,所以我将研究一下这一点。再次感谢