Я пишу простой многопоточный буфер. Его цель - хранить данные со звуковой карты, пока я не смогу их обработать. Он реализован в виде простого связанного списка (Элемент = элемент списка, DataQueue = фактический буфер, DataChunk = объект с данными):
class Element{
private:
Element *next;
DataChunk *data;
public:
Element(DataChunk *data);
~Element();
DataChunk *getData();
Element *nextElement();
void setNextElement(Element *nextElement);
};
class DataQueue{
private:
int size;
Element *top;
Element *last;
HANDLE lock;
public:
DataQueue();
void append(DataChunk *chunk);
Element *cut(int *cutSize);
};
Element::Element(DataChunk *data){
this->data = data;
this->next = NULL;
}
Element::~Element(){
delete data;
}
DataChunk *Element::getData(){
return data;
}
Element *Element::nextElement(){
return next;
}
void Element::setNextElement(Element *nextElement){
this->next = nextElement;
}
DataQueue::DataQueue(){
size = 0;
top = NULL;
last = NULL;
lock = CreateEvent(NULL, TRUE, FALSE, TEXT("Lock"));
if(lock == NULL){
printf("Error code: %ld\n", GetLastError());
exit(EXIT_FAILURE);
}
}
void DataQueue::append(DataChunk *chunk){
WaitForSingleObject(lock, INFINITE);
SetEvent(lock);
Element *element = new Element(chunk);
if(top == NULL){
top = element;
}
else{
last->setNextElement(element);
}
last = element;
ResetEvent(lock);
}
Element *DataQueue::cut(int *cutSize){
WaitForSingleObject(lock, INFINITE);
SetEvent(lock);
Element *toReturn = top;
*cutSize = size;
top = NULL;
last = NULL;
size = 0;
ResetEvent(lock);
return toReturn;
}
Шаблон использования выглядит следующим образом:
Аудио драйвер (ASIO) использует функции обратного вызова, чтобы уведомить меня, когда его буферы готовы к обработке. Это происходит много (дюжина раз в секунду). Но мне нужно обрабатывать данные только один раз в 5 секунд или около того. Поэтому я использую свой собственный буфер для хранения звуковых данных за 5 секунд. Драйвер создает свой собственный поток и выполняет функцию обратного вызова. Из этого потока я вызываю append () и добавляю данные из буферов устройств в мой буфер. Когда появляется фактический поток обработки, он обрезает буфер, получая первый элемент и сбрасывая буфер до 0 элементов.
Проблема заключается в синхронизации потоков. Функции cut () и access () являются взаимоисключающими. У меня есть Event HANDLE, и я жду этого события. У меня есть некоторый опыт работы с Java, и я совершенно новичок в этих Win32 API. Я делаю это правильно? Точно так же происходит сбой программы на WaitForSingleObject, возможно потому, что у меня нет права доступа SYNCHRONIZATION (c0000005). Как я могу установить поток, созданный драйвером? Будет ли это работать даже при наличии нескольких потоков обработки?