2014-02-13 3 views
1

이 올바른 방법은 스레드 안전 큐을 C++로 처리 할 수 ​​있으며 unsigned char * 배열 바이너리 데이터를 처리 할 수 ​​있습니까?C++에서 스레드 안전 큐

데이터가 주 스레드에서 생성되었으며 생성 된 pthread가 아니라는 점에 유의하십시오. 이는 pthread_mutex_t가 실제로 푸시 및 팝에서 올바르게 작동하는지 질문합니다.

스레드

#include <queue> 
#include <pthread.h> 

class ts_queue 
{ 

private: 

    std::queue<unsigned char*> _queue_; 
    pthread_mutex_t mutex; 
    pthread_cond_t cond; 

public: 

    ts_queue() 
    { 
     pthread_mutex_init(&mutex, NULL); 
     pthread_cond_init(&cond, NULL); 
    } 

    void push(unsigned char* data) 
    { 
     pthread_mutex_lock(&mutex); 

     _queue_.push(data); 

     pthread_cond_signal(&cond); 
     pthread_mutex_unlock(&mutex); 
    } 

    void pop(unsigned char** popped_data) 
    { 
     pthread_mutex_lock(&mutex); 

     while (_queue_.empty() == true) 
     { 
      pthread_cond_wait(&cond, &mutex); 
     } 

     *popped_data = _queue_.front(); 
     _queue_.pop(); 

     pthread_mutex_unlock(&mutex); 
    } 
}; 

소비자 TEST 안전 대기열 :

void *consumer_thread(void *arguments) 
{ 
    ts_queue *tsq = static_cast<ts_queue*>(arguments); 

    while (true) 
    { 
     unsigned char* data = NULL; 

     tsq->pop(&data); 

     if (data != NULL) 
     { 
      // Eureka! Received from the other thread!!! 
      // Delete it so memory keeps free. 
      // NOTE: In the real scenario for which I need 
      // this class, the data received are bitmap pixels 
      // and at this point it would be processed 
      delete[] data; 
     } 
    } 

    return 0; 
} 

생산자 TEST :

void main() 
{ 
    ts_queue tsq; 

    // Create the consumer 
    pthread_t consumer; 
    pthread_create(&consumer, NULL, consumer_thread, &tsq)); 

    // Start producing 
    while(true) 
    { 
     // Push data. 
     // Expected behaviour: memory should never run out, as the 
     // consumer should receive the data and delete it. 
     // NOTE: test_data in the real purpose scenario for which I 
     // need this class would hold bitmap pixels, so it's meant to 
     // hold binary data and not a string 

     unsigned char* test_data = new unsigned char [8192]; 
     tsq.push(test_data); 
    } 

    return 0; 
} 

답변

1

이 어떻게 요 소비자는 데이터를 얻지 못한다는 것을 알고 있습니까? 프로그램을 사용해 보았을 때 세분화 오류가 발생했고 GDB에서 소비자가 포인터를 얻었지만 잘못되었습니다.

귀하의 문제는 귀하가 _queue_ 회원에 대한 데이터 경쟁이 있다는 것입니다. push() 전화 _queue_.push(data) (_queue_에 쓰기)를 동시에 발생할 수 pop_mutex하지만 push()pop()를 누른 상태로 두 스레드를 일으키는 원인이 push_mutexpop() 통화 _queue_.front() (_queue_의 읽기) 및 _queue_.pop() (_queue_에 다른 쓰기)를 누른 상태에서 동시에 쓰기 (및 독서) _queue_, 고전적인 데이터 경주.

관련 문제