2012-10-27 2 views
7

프로그램을 종료 할 준비가 될 때까지 루프에 앉아있는 스레드가 있습니다.이 스레드는 루프에서 빠져 나오기를 원합니다. 나가서 std::thread::join라고 부를 수 있습니다. C++ 03 시절에 스레드를 종료 할 때 알려주기 위해 잠금으로 보호 된 bool을 사용했습니다. 이번에는 새로운 원자학 라이브러리 (특히 std::atomic_bool)를 활용할 것이라고 생각했지만 문제가 있습니다. 내가 컴파일 할 때C++에서 std :: thread와 함께 atomics 사용하기

#include <atomic> 
#include <thread> 
#include <cstdio> 

using namespace std; 

void setBool(atomic_bool& ab) 
{ 
    ab = true; 
} 

int main() 
{ 
    atomic_bool b; 
    b = false; 
    thread t(setBool, b); 
    t.join(); 
    printf("Atomic bool value: %d\n", b.load()); 
    return 0; 
} 

thread t의 선언은 this 괴물을 뱉어 : 다음은 내 테스트 케이스이다. 오류의 중앙 부분이 될 것으로 보인다 :

유형의 const가 아닌 참조의 잘못된 초기화 '표준 : atomic_bool &'유형 '표준 : atomic_bool'

왜의를 rvalue에서 atomic_bool에 대한 참조를 얻을 수 없습니까? 대신 무엇을해야합니까?

+0

@NicolBolas 어떻게 그렇게됩니까? 스레드간에 데이터를 공유하는 표준 방법에 액세스하기 전에 뮤텍스로 변수를 잠그지 않습니까? –

+0

아, 맞아. 절대로 ... –

답변

13

명시 적으로 참조를 스레드에 전달해야합니다. std::ref을 사용하면 std::reference_wrapper이 만들어지며 복사가 가능하여 해당 기능을 수행 할 수 있습니다.

thread t(setBool, std::ref(b)); 

그렇지 않으면 복사 할 수없는 원자를 복사하려고합니다.

+0

왜 복사를 시도합니까? 참조 인수에 대한 변수 이름을 제공하지 않으면 전통적으로 해당 변수를 참조로 전달합니까? –

+4

@ slavik262 네, 맞습니다. 스레드 생성자는 실행 시점을 모르는 함수를 호출 할 때 참조를 전달한 경우 참조가 유효하지 않을 수 있으므로 인수를 복사하여 안전하게 저장합니다. 명시 적으로 ref-wrapper를 사용하는 경우 객체가 스레드보다 오래 유지되는지 확인하는 것이 좋습니다. – inf

+0

설명 주셔서 감사합니다! –

4

bamboon이 설명한대로 std::thread의 가변 인수 생성자를 통해 참조로 전달되도록하려면 bamboon을 std::ref으로 포장해야합니다. (동일은 std::async에도 적용됩니다.) 이처럼 직관적이지 않은 동작을 방지하려면 예상대로 정확하게 동작하는 람다를 사용할 수 있습니다. 그냥 스레드를 만들려면이를 사용 람다와

thread t([&]{ setBool(b); }); 

는 심판/CREF의 말도 필요 없다 참조로 인수를 전달하고자 할 때.

난 그냥뿐만 아니라이 우연히
+0

감사!나는 람다에 대해 잘 알고있다. (나는 끝내 준다.) 나는 문제를 분리하기 위해 나의 테스트 케이스에 사용했던 C++ 11의 마술의 양을 최소화하고 싶었다. –

0

, 당신은 또한과 같이 원자에 주소를 전달하여 문제를 해결할 수 있다고 생각 :

: 함수는 원자에 대한 포인터를 취

std::atomic<bool> b{false}; 
std::thread t(setBool, &b); 

void setBool(std::atomic<bool>* ab) 

나는 받아 들여지는 관습이 무엇인지 잘 모르겠다.이 방법으로 원자 포인터에 널 포인터를 전달할 수 있다고 생각하지만, 왜 그렇게하고 싶은지 확신 할 수 없다.

관련 문제