2016-07-05 4 views
3

특정 프로젝트에서 내 자신의 원자 클래스를 구현하고 있습니다. 에서 C++ 11 원자 라이브러리에 액세스 할 수 없습니다. 반환 값 레지스터 및 소멸자 호출 순서

class CAtomicLong 
{ 
public: 

    CAtomicLong(long lVal) : m_lValue(lVal) {} 

    long operator+(long lVal) 
    { 
     CAutoLock lock(m_lock); 
     m_lValue += lVal; 
     return m_lValue; 
    } 
private: 

    CMyMutex m_lock; 
    long m_lValue; 
}; 

CMyMutex가 뮤텍스 주위에 사용자 지정 래퍼이며, CAutoLock 누구의 소멸자의 건설 기간 동안 전달 된 객체의 잠금을 해제하는 클래스라고 가정 : 지금까지 다음과 같은 코드가 있습니다. 이러한 세부 사항은 대체로이 질문과 관련이 없습니다.

내가 알고 싶은 것은 m_lValue을 다음과 같이 반환하는 것이 안전한지 여부입니다. 즉 을 반환하기 위해 레지스터에 복사 될 것입니까? 전에 lock에 대한 소멸자가 호출됩니까? 소멸자가 이라면 전에 반환 레지스터가 설정되어 있기 때문에 다른 스레드가 반환을 위해 복사 중일 때 m_lValue을 수정하기 시작할 수 있기 때문에 찢어진 읽기 및 쓰기가 걱정됩니다.

Visual Studio에서 이와 같은 코드로 디스 어셈블리를 한 번 보았습니다. 전에이 호출되기 전에 반품 전화가 표시되는 것으로 보입니다. 그러나 a) 나는 실제로 무엇인지 모르겠습니다. 어셈블리로보고 (아직도 배우고 있어요 :)) 그리고 b) 이것이 표준 행동인지 다시 모르겠다. (나는 여전히 배우고있다.) 이 잠재적 문제의 안전한 해결 방법은

long operator+(long lVal) 
{ 
    CAutoLock lock(m_lock); 
    long lTemp = (m_lValue += lVal); 
    return lTemp; 
} 

입니다 ...하지만이 과잉이면 차라리 지금 알고있는 것입니다.

+1

어떤 플랫폼을 사용하고 있습니까? 그들 대부분은 원자 증가를위한 내장 함수를 가지고 있으며, 뮤텍스 대신 사용할 수 있습니다. – Dani

+0

이것은 Windows, Solaris Sparc 및 Linux에서 작동해야합니다. Windows에서 원자 증가 함수가 있지만 atomic 검색 함수를 찾을 수 없으며 Solaris에서 필요한 함수에 액세스 할 수 없습니다. 그러므로이 질문. – Wad

+0

C++에는 "레지스터"가 없습니다. 코드는 작성된대로 정확합니다. –

답변

5

코드가 정확합니다. [stmt.return]/3 말한다

호출의 결과의 복사본 초기화 리턴 명령문의 피연산자에 의해 설정된 전체 표현식의 끝으로 임시의 파괴 전에 서열화 된 는 차례로 전에 return 문을 둘러싸는 블록의 지역 변수 (6.6)가 파기되기 전에 순서가 지정됩니다.