2009-05-28 7 views
3

내 C++ 프로그램에서 pthread (Linux에서 실행)를 기반으로하는 트리거 및 대기 멤버 함수로 CEvent 클래스가 있습니다. 대기중인 프로세스가 하나있는 경우 구현이 매우 명확합니다 (예 : 온라인의 많은 사례). 그러나 이제는 여러 스레드가 이벤트를 기다리고 있고 trigger()가 호출 될 때 모두 깨어 있어야한다는 요구 사항을 만족해야합니다. 두 번째 조건으로 trigger()가 호출 될 때 대기중인 스레드 만 깨어 있어야합니다.대기 스레드를 깨우는 pthread 기반 이벤트

내 현재 코드 :

void CEvent::trigger() { 
    pthread_mutex_lock(&mutex); 
    wakeUp = true; 
    pthread_cond_broadcast(&condition) 
    pthread_mutex_unlock(&mutex); 
    wakeUp = false; 
} 

void CEvent::wait() { 
    pthread_mutex_lock(&mutex); 
    while (!wakeUp) 
     pthread_cond_wait(&condition, &mutex) 

    pthread_mutex_unlock(&mutex); 
} 

이 거의 한, 나는 다시 false로 모닝콜을 설정하기 전에 모든 스레드가 웨이크 업 대기로 작동하는 것 같다. 그러나 wakeUp 브로드 캐스트와 리셋 사이에 wait()를 호출하는 다른 (또는 같은) 쓰레드도 즉시 깨어 나면 받아 들일 수 없습니다. mutext 잠금 해제 전에 wakeUp = false로 설정하면 스레드가 깨어나지 않습니다.

내 질문 : * pthread_cond_broadcast는 언제 반환됩니까? 나는. 모든 스레드가 깨어나거나 이전에 돌아올 수있을 때만 반환된다는 보장이 있습니까? *이 문제에 대한 권장 해결책이 있습니까?

답변

3

이전의 위조 답변을 무시하십시오. 트리거 스레드가 뮤텍스를 잠금 해제하고 (따라서 대기중인 스레드를 해제하는) 시간 사이에 경합이 발생하고 wakeUp 값을 설정합니다. 즉, 다른 (대기 중이 지 않은) 스레드가 들어 와서 뮤텍스를 잡고 실제 값인 wakeUp을보고 기다리지 않고 종료 할 수 있습니다. 또 하나의 버그는 wakeUp이 리셋 된 후 기다리고있는 스레드가 깨어나고 즉시 대기를 다시 시작한다는 것입니다.

이 문제를 해결하는 한 가지 방법은 count를 사용하는 것입니다. 대기중인 각 스레드는 카운트를 증가시키고 트리거는 다시 시작하기 전에 많은 스레드가 깨어날 때까지 대기합니다. 그런 다음 대기하지 않는 스레드가 이런 일이 발생할 때까지 기다리지 못하게해야합니다.

// wake up "waiters" count of waiting threads 
void CEvent::trigger() 
{ 
    pthread_mutex_lock(&mutex); 

    // wakey wakey 
    wakeUp = true; 
    pthread_cond_broadcast(&condition); 

    // wait for them to awake 
    while (waiters>0) 
     pthread_cond_wait(&condition, &mutex); 

    // stop waking threads up 
    wakeUp = false; 

    // let any "other" threads which were ready to start waiting, do so 
    pthread_cond_broadcast(&condition); 
    pthread_mutex_unlock(&mutex); 
} 

// wait for the condition to be notified for us 
void CEvent::wait() 
{ 
    pthread_mutex_lock(&mutex); 

    // wait for us to be allowed to start waiting 
    // we have to wait until any currrently being woken threads have gone 
    while (wakeUp) 
     pthread_cond_wait(&condition, &mutex); 

    // our turn to start waiting 
    waiters ++; 

    // waiting 
    while (!wakeUp) 
     pthread_cond_wait(&condition, &mutex); 

    // finished waiting, we were triggered 
    waiters --; 

    // let the trigger thread know we're done 
    pthread_cond_broadcast(&condition); 
    pthread_mutex_unlock(&mutex); 
} 
+0

감사합니다.이 트릭을 수행하는 것 같습니다. –