2016-10-18 7 views
0

우선 순위가 높은 스레드에서 실행되는 높은 우선 순위 기능을 가진 dll이 있습니다. 이 dll은 진행 상황을보고해야합니다. 기본적으로 콜백 시스템이 사용됩니다. 문제는 dll이 콜백이 완료되는 데 걸리는 시간을 제어 할 수 없다는 것입니다. 즉, 우선 순위가 높은 기능은 콜백 구현에 따라 달라지며 이는 받아 들일 수 없습니다.스레드 안전 큐에서 잠금 범위를 좁게하십시오.

아이디어는 진행 중 알림을 버퍼링하고 콜백을 호출하는 클래스를 갖는 것입니다.

저는 C++ 11을 처음 접했고 기능을 스레딩하고 가능성을 발견하려고합니다. 구현이 있지만 문제가 있습니다 (적어도 하나는 지금 볼 수 있음). 기다린 후에 스레드가 깨어 나면 뮤텍스가 다시 획득되고 다음 대기 때까지 획득 상태를 유지합니다. 즉, 긴 작업이 계속 진행되는 동안 잠금이 획득됩니다. 진행 상황을 추가하면 여기에서 차단됩니다. 기본적으로 많은 이득을위한 코드. 코드를이 코드로 변경하려고 생각했지만 이것이 올바른 구현인지 여부는 알 수 없습니다.

 Progress progress = queue.front(); 
     queue.pop(); 
     lock.unlock(); 
     // Do lengthy operation with progress 
     lock.lock(); 

나는 조건 변수를 기다릴 필요가 있다고 생각하지만 잠금 장치에 연결하면 안된다. 어떻게 할 수 있는지 모르겠습니다. 더미 잠금 장치를 전달하고 큐를 보호하기 위해 다른 잠금 장치를 사용합니까? 이 문제는 C++ 11에서 어떻게 처리되어야합니까?

헤더 파일

#include <atomic> 
#include <condition_variable> 
#include <mutex> 
#include <thread> 
#include <queue> 

#include "Error.h" 
#include "TypeDefinitions.h" 


struct Progress 
{ 
    StateDescription State; 
    uint8 ProgressPercentage; 
}; 

class ProgressIsolator 
{ 
public: 
    ProgressIsolator(); 
    virtual ~ProgressIsolator(); 

    void ReportProgress(const Progress& progress); 
    void Finish(); 

private: 
    std::atomic<bool> shutdown; 
    std::condition_variable itemAvailable; 
    std::mutex mutex; 
    std::queue<Progress> queue; 
    std::thread worker; 

    void Work(); 
}; 

CPP 파일이 향하고있다하지만이 같은 기능을 제공하지 않는 경우 내가 볼

#include "ProgressIsolator.h" 

ProgressIsolator::ProgressIsolator() : 
    shutdown(false), 
    itemAvailable(), 
    worker([this]{ Work(); }), 
    progressCallback(progressCallback), 
    completedCallback(completedCallback) 
{ 
    // TODO: only continue when worker thread is ready and listening? 
} 

ProgressIsolator::~ProgressIsolator() 
{ 
    Finish(); 
    worker.join(); 
} 

void ProgressIsolator::ReportProgress(const Progress& progress) 
{ 
    std::unique_lock<std::mutex> lock(mutex); 
    queue.push(progress); 
    itemAvailable.notify_one(); 
} 

void ProgressIsolator::Finish() 
{ 
    shutdown = true; 
    itemAvailable.notify_one(); 
} 

void ProgressIsolator::Work() 
{ 
    std::unique_lock<std::mutex> lock(mutex); 

    while (!shutdown) 
    { 
     itemAvailable.wait(lock); 
     while (!queue.empty()) 
     { 
      Progress progress = queue.front(); 
      queue.pop(); 
      // Do lengthy operation with progress 
     } 
    } 
} 

답변

0
void ProgressIsolator::Work() 
{ 
    while (!shutdown) 
    { 
     Progress progress; 
     { 
      std::unique_lock<std::mutex> lock(mutex); 
      itemAvailable.wait(lock, [this] { return !queue.empty(); }); 
      progress = queue.front(); 
      queue.pop(); 
     } 
     // Do lengthy operation with progress 
    } 
} 
+0

. 밀어 넣기가 진행 중이고 대기열에 항목이 두 개 이상있는 경우 Finish 메서드가 호출되면 모든 항목이 팝되지 않습니다. 몇 가지 추가 정보에서 잠깐만 기다려야 겠지만 잠김은 대기열을 보호하지 않고 상태 변수를 보호하기위한 것입니다. –