2016-10-31 10 views
4

후속 조치는 Can C++11 condition_variables be used to synchronize processes?입니다.std :: condition_variables를 카운팅 세마포로 사용할 수 있습니까?

카운트 세마포어로 std :: condition_variable 개체를 사용할 수 있습니까?

메타 링크는 객체가 std :: mutex에 바인딩되어있는 것처럼 보이지 않으므로 바이너리 세마포어로만 사용할 수 있습니다. here, herehere을 (를) 포함하여 온라인에서 보았지만 이러한 개체를 카운팅 세마포로 사용하는 참조 또는 예제를 찾을 수 없습니다.

+0

? 위의 텍스트를 읽으면 단일 코어 머신 용 프로그램을 빌드해야한다는 요구 사항이있을 수 있으며 해당 세마포어 메커니즘을 사용하고 싶거나 OS 세마포어 주위에 래퍼를 사용하는 정말 오래된 코드가 있다는 생각을하게됩니다. 행동. 좀 가까이 있니? – AhiyaHiya

+0

@AhiyaHiya : 개인 학습을위한 학업 적 연습입니다. 재미있는 코드를 작성 중이며 posix 기반 동기화 메커니즘 (pthread_mutex_t, sem_t)에서 C++ 11 기본 메커니즘으로 마이그레이션하려고합니다. 나는 C++ 11이'std :: mutex'를 제공하는 것을 보았는데, 왜 세마포어가 없는지 의아해했다. 추가 읽기에서는'std :: condition_variable'이 세미 - 세마포어 기능을 구현하는 데 사용된다는 것을 알았지 만 그 기능과 한계를 배우고 이해하려고합니다. 세마포어와 완전히 일치하지는 않지만 아직 잘 모르겠습니다 ... 여전히 공부하고 있습니다. – StoneThrow

+0

잘 공부 한 멀티 코어 동시/병렬 프로그래밍 가이드를보고 공부하고 싶다면 "효과적인 동시성"시리즈에서 허브 셔터의 병행 프로그래밍의 기둥을 검토해야합니다. https://herbsutter.com/category/effective -concurrency/ – AhiyaHiya

답변

1

예.

struct counting_sem { 
    counting_sem(std::ptrdiff_t init=0):count(init) {} 
    // remove in C++17: 
    counting_sem(counting_sem&& src) { 
    auto l = src.lock(); // maybe drop, as src is supposed to be dead 
    count = src.count; 
    } 
    counting_sem& operator=(counting_sem&& src) = delete; 
    void take(std::size_t N=1) { 
    if (N==0) return; 
    auto l = lock(); 
    cv.wait(l, [&]{ 
     if (count > 0 && count < (std::ptrdiff_t)N) { 
     N -= count; 
     count = 0; 
     } else if (count >= (std::ptrdiff_t)N) { 
     count -= N; 
     N = 0; 
     } 
     return N == 0; 
    }); 
    } 
    void give(std::size_t N=1) { 
    if (N==0) return; 
    { 
     auto l = lock(); 
     count += N; 
    } 
    cv.notify_all(); 
    } 
    // reduce the count without waiting for it 
    void reduce(std::size_t N=1) { 
    if (N==0) return; 
    auto l = lock(); 
    count -= N; 
    } 
private: 
    std::mutex m; 
    std::condition_variable cv; 
    std::ptrdiff_t count; 

    auto lock() { 
    return std::unique_lock<std::mutex>(m); 
    } 
    auto unlocked() { 
    return std::unique_lock<std::mutex>(m, std::defer_lock_t{}); 
    } 
}; 

코드는 테스트되지 않았거나 컴파일되었지만 사운드는 디자인되었습니다.

take(7)for(repeat 7 times) take()과 같지 않습니다. 대신 충분하지 않은 경우 차단할 수있는만큼 걸립니다. 정도가 될 때까지 아무것도하지 않도록

수정은 간단합니다 : 당신은 왜 세마포어와 같은 개체를 찾고 있습니다

 if (count >= (std::ptrdiff_t)N) { 
     count -= N; 
     N = 0; 
     } 
+0

코드 예제의 요지를 얻었습니다. 감사합니다. 그래서 얻은 인상은'std :: condition_variable'은 실제로 세마포어와 같지 않지만 세마포어와 기능적으로 동일한 객체를 만드는 데 사용될 수 있다는 것입니다. 나는 왜 C++ 표준기구가 일반 오래된 세마포어를 제공하는 대신이 방법을 사용했는지 궁금합니다. 결국 그들은 기초적인 컴퓨터 과학 객체입니다. – StoneThrow

+0

조건 변수가 효율적으로 하드웨어에 매핑되기 때문에 (위의 가정은 위의 메시지는 정수 카운트가 <= 0이지만 대부분의 메시지를 릴레이하는 데 사용할 수 있습니다. 미래는 준비되어있다, etc.). 금속이 제공하는 것을 휴대용 랩퍼에서 쉽게 추상화합니다. – Yakk

+0

@Yakk _ 모든 것을 "원자 적으로"취하지는 않습니다. ./ Er ...하지만 그럴 수 있습니다 ... 아마도 "while"대신에 "if"를 의미했을 것입니다. 'while'을 사용하면 술어가 한 번 호출되고 'count'가 'N'보다 높으면 'count'회 반복하고 'true'를 반환합니다. – screwnut