Синхронное чтение IOBluetooth

Прямо сейчас я работаю над программой, использующей IOBluetooth, и мне нужно синхронное чтение, т.е. я вызываю метод, он записывает заданное количество байтов в порт, затем читает заданное число и возвращает их. В настоящее время у меня есть сложная система NSThreads, NSLocks и NSConditions, которая хоть и работает, но очень медленно. Кроме того, после определенных вызовов мне нужно убедиться, что нет лишних данных, поэтому я обычно очищаю буфер, но с асинхронным обратным вызовом IOBluetooth это невозможно - любые мысли о том, как убедиться, что несмотря ни на что, все данные, полученные после конкретная точка - это данные, полученные после этой точки?

Я действительно вообще не имел дело с синхронизацией и многопоточностью такого типа, поскольку вся работа, которую я проделал до сих пор, использовала синхронные вызовы, поэтому я был бы признателен за любые мысли по этому поводу.

Вот обратный вызов для входящих данных (объект incomingData — это NSMutableData):

- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength {
    [dataLock lock];
    NSData *data = [NSData dataWithBytes:dataPointer length:dataLength];
    [incomingData appendData:data];

    if (dataWaitCondition && [incomingData length] >= bytesToWaitFor) {
        [dataWaitCondition signal];
    }

    [dataLock unlock];
    [delegate bluetoothDataReceived];
}

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

- (NSData *)waitForBytes:(int)numberOfBytes {

    bytesToWaitFor = numberOfBytes;
    [dataLock lock];
    dataWaitCondition = [[NSCondition alloc] init];
    [dataWaitCondition lock];
    [dataLock unlock];
    while ([incomingData length] < numberOfBytes) {
        [dataWaitCondition wait];
    }
    [dataLock lock];
    NSData *data = [incomingData copy];
    [dataWaitCondition unlock];
    dataWaitCondition = NULL;
    [dataLock unlock];

    return data;
}

person Justin Mrkva    schedule 26.02.2011    source источник


Ответы (1)


Выполнение любого синхронного ввода-вывода/коммуникации вызовет у вас проблемы.

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

person mringwal    schedule 22.09.2011
comment
На самом деле я частично решил эту проблему, и да, вы абсолютно правы, но более серьезная проблема заключалась в том, что асинхронные вызовы с новыми данными поступают слишком медленно. Приложение работает в режиме реального времени, но мы получаем входящие данные от IOBluetooth только с частотой 1-5 Гц, что слишком медленно. Есть идеи, почему данные поступают так медленно? Мне нужно, чтобы звонки поступали как можно быстрее. - person Justin Mrkva; 03.10.2011
comment
RFCOMM имитирует последовательный порт, но должен отправлять пакеты данных L2CAP этих последовательных данных. Из-за этого на отправляющей стороне могут возникнуть очереди, возможно, это можно заставить отправлять чаще. Вы также можете проверить с помощью PacketLogger, насколько быстро поступают ваши данные и буферизуются ли они на стороне OS X. - person mringwal; 17.10.2011