2012-03-07 7 views
8

C++ (11)는 thread-safe initialization of static variables과 같은 기능을 제공, 우리는 예를 들어 말할 것 그 질문에 인용 :C++ 11로 컴파일/링크 된 타사 스레드 라이브러리에 C++ 11 스레드 안전성 보장이 적용됩니까?

Logger& g_logger() { 
    static Logger lg; 
    return lg; 
} 
그래서 표면적으로이 관계없이 사실이다

여부를 C++ 11 컴파일러로 컴파일 모듈 (?) 스레드 헤더를 포함하거나, 본문에 스레드를 생성합니다. C++ 11 스레드를 사용하는 다른 모듈과 링크되어 있고 함수가 호출 된 경우에도 보증을 제공합니다.

하지만이 코드를 호출하는 "다른 모듈"이 C++ 11 스레드를 사용하지 않았지만 Qt의 QThread과 같은 것일 경우 어떻게해야합니까? C++ 11의 이러한 보증을 할 수없는 범위에서 원자를 초기화하는 것입니까? 아니면 C++ 11로 컴파일 된 다음 다른 C++ 11 코드와 링크 된 모듈의 단순한 사실은 관계없이 보증을 얻을 수 있음을 암시합니다.

누구나 이와 같은 문제가 다루어지는 좋은 참고 자료를 알고 있습니까?

+0

정적 초기화는 언어 속성입니다. 어떻게 이것이 특정 라이브러리에 의해 영향을받을 수 있는지 나는 모르겠다. – pmr

+2

@pmr 예를 들어 위의 정적 메모리는 프로그램 시작 부분에 할당되었지만 정적 인 내부 함수가 호출 될 때 생성자가 처음으로 실행되기 때문에 조금 까다로운 것처럼 보입니다. 이를 달성하기 위해 기본 스레드 모델에 대한 옴성을 요구하는 것 같습니다. QThread/C++ 11thread를 섞으면 올바른 결과를 얻을 수 있습니다. 새로운 바이너리 요구 사항이 적용될 수있는 약간의 기회가 있습니다. . – HostileFork

+0

@HostileFork : (C++과 qt) 모두 스레딩을 위해 동일한 OS 기능을 사용하는 한, 어떻게 잘못 될지 알 수 없습니다. 또한 왜 둘 다 OS 스레딩 기능을 사용하지 않아야하는지 알지 못합니다. – PlasmaHH

답변

4

이 예에서는 스레드가 구현되는 방식이 아니라 메모리 모델을 사용합니다. 누구든지이 코드를 실행하면 동일한 지침이 실행됩니다. 두 개 이상의 코어가이 코드를 실행하면 메모리 모델을 따릅니다.

기본 구현은 동일하다 :

std::mutex mtx; 
Logger * lg = 0; 
Logger& g_logger() { 
    std::unique_lock<std::mutex> lck(mtx); 
    if (lg == 0) 
     lg = new Logger; 
    return *lg; 
} 
이 코드는 재확인 잠금 패턴 (DCLP)를 사용하여 최적화 될 수있다

합니다 (86에서 예), 특정 프로세서 구조에있는 수도 훨씬 빠르다. 또한 컴파일러가이 코드를 생성하기 때문에 순진한 DCLP를 손상시키는 미친 최적화를하지 않을 것입니다.

+0

멋지게 ... 감사합니다. 안전하다고 생각되는 컨센서스가있는 것처럼 보입니다. FYI : 내가 그것을 조사한 이유는이 시나리오를 다루는 것이 었습니다 ... http://stackoverflow.com/questions/9507973/how-to-mitigate-user-facing-api-effect-of-shared-members-in -templated-classes – HostileFork

7

누구에게도 이와 같은 문제가있는 좋은 참조를 알고 있습니까?

확실히. C++ 표준. C++ 코드의 동작을 설명합니다. 라이브러리가 C++ 코드 인 경우이 동작을 따라야합니다. 그래서 네, 당신은 자신의 코드 인 것처럼 동일한 보장을받습니다.

정확히 어떻게 컴파일러/런타임/OS/그 밖의 모든 것이 문제가되지 않습니다. C++ 표준은 그것이 처리된다는 것을 보장합니다.

+0

Point에 따라 유효한 실행 스레드입니다. 그러나 그것이 나의 문제 이건 아니건간에 관계없이 나는 GCC와 Qt를 사용하여 "꺼내라"는 마법을 짓는 지 알고 싶다. 기술적인 관점에서 볼 때 C++ 03은 정적입니다.a 라이브러리가 C++ 11'icallthestatic '실행 파일에 링크되어 있으면 링커가이 작업을 수행 할 수 없을 것입니다. 그러나 이것은 "C++ 03 코드를 C++ 11과 링크 할 수없고 C++ 11 시스템을 보증 할 수 없습니다"라는 더 넓은 문제를 지적합니다. ... – HostileFork

+0

C++ 03 코드는 C++ 03처럼. 따라서 C++ 03 라이브러리에 링크하면 C++ 11에 의해서만 제공되는 보증을 구현할 수 없습니다. – jalf