2011-11-27 118 views
1

我在写一个简单的多线程缓冲区。它的目的是保存声卡中的数据,直到我可以处理它们。它被实现为简单的链表(元素=列表元素,DataQueue =实际缓冲,DataChunk =与数据对象):获取SYNCHRONIZE访问权限

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秒的声音数据。 Driver创建自己的线程并执行回调函数。从这个线程中,我调用append()并将设备缓冲区中的数据追加到我的缓冲区中。当实际的处理线程出现时,它通过获取第一个元素并将缓冲区重置为0个元素来切割缓冲区。

问题是线程同步。 cut()和access()函数是互斥的。我有事件处理和我等待这个事件。我有一些Java的经验,而且对于这些Win32 API来说是全新的。我做对了吗?就像这样,程序在WaitForSingleObject上崩溃,可能是因为我没有SYNCHRONIZATION访问权限(c0000005)。我怎样才能将它设置为由驱动程序创建的线程?即使在有多个处理线程的情况下,这也可以工作吗

+0

不会有一个循环缓冲区比链接列表更合适吗? –

+0

首先,在WaitForSingleObject之后立即调用SetEvent根本没有意义。当WaitForSingleObject返回时,事件被设置并且它必须由另一个线程设置。 –

+1

我认为你使用EnterCriticalSection将WaitForSingleObject搞混了。 –

回答

1

EnterCriticalSection做了诡计。