我正在编写一个简单的多线程缓冲区。它的目的是保存声卡中的数据,直到我可以处理它们。它被实现为一个简单的链表(Element = list元素,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()函数是互斥的。我有事件处理,我等待这个事件。我有一些Java经验,对这些Win32 API来说是全新的。我做得对吗?就像这样,程序在WaitForSingleObject上崩溃,可能是因为我没有SYNCHRONIZATION访问权限(c0000005)。如何将其设置为驱动程序创建的线程?即使有多个处理线程,这还能工作吗?
答案 0 :(得分:1)
EnterCriticalSection做到了这一点。