2012-12-13 3 views
5

C++ 11 원자 작업으로 unique_ptr을 안전하게 이동시킬 수 있습니까?스레드 안전 unique_ptr move

std::atomic<std::unique_ptr<SyncToken>> syncToken; 

와 뮤텍스의 필요성을 피할 수 :

현재 나는이

std::unique_ptr<SyncToken> DataManager::borrowSyncToken() 
{ 
    std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex); 
    return std::move(syncToken); 
} 

같은 코드가 단순히 선언처럼, 좀 더 우아한 방법이 있는지 궁금합니다. 아니면 아마도 여기에 자물쇠가 전혀 신경 쓸 필요가 없으며 std :: move는 이미 원자 적입니다.

연구 후에 나는 지금까지 나에게 보인다 만든 :

  • 자체를 이동 :: 성병은 원자하지 않고 동시에 내 메소드를 호출 주변 그렇지 않으면 2 스레드가 2 장으로 끝낼 수있는 몇 가지 동기화가 필요 정의되지 않은 포인터 중 일부
  • std :: atomic 선언은 나를 위해 컴파일되지만 초기화하고 이동하는 방법을 알지 못합니다.

답변

2

아니요. 불가능합니다.

std::atomic에 전달하는 값 T은 쉽게 복사 할 수 있어야합니다. std::unique_ptr은 복사 할 수 없습니다. std::atomic::load 또는 std::atomic::store과 같은 작업은 T 개체를 값으로 사용합니다.

std::atomic에있는 내용물을 포장해도 원자 값에서 조작하지 않습니다.

원자적인 컨텍스트에서 std::unique_ptr을 사용할 때 자원 관리와 관련하여 문제가 발생할 수 있다는 사실을 생각해야합니다. 얼마나 많은 스레드가 여전히 데이터를 참조하는지 알 수 없지만이 문제는 원자 참조 계산을 사용하는 std::shared_ptr으로 해결할 수 있습니다. (std::atomic_is_lock_free 함수를 사용하여 실제로 원자인지 여부를 확인해야합니다.

코드에서 볼 때 내가 우연히 만났던 한 가지는 borrowSyncToken 함수의 의도입니다. 그것은 빌려 왔지만 std::unique_ptr을 이동하여 호출자에게 토큰 소유권을 넘겨 주며, 소유권은 어떻게 되돌려지고 다른 스레드는 현재 DataManager가 토큰을 소유하지 않을 때 어떻게됩니까?

+0

답장과 std :: shared_ptr에 대한 토론에 감사드립니다. 의도를 위해 : 코드는 단순화되었지만 호출자가 토큰을 사용할 수 없다는 것을 알 수 있도록 나중의 스레드에 nullptr을 반환한다고 생각합니다. 여기서 해결 된 문제는 다른 설명에서 설명 할 것입니다. –

+0

클라이언트는 DataManager에서 읽기, 쓰기라는 두 가지 유형의 작업을 수행합니다. 그 시간에 단 하나의 클라이언트 만 쓸 수 있습니다. ** 클라이언트는 스레드가 아닙니다. ** - 때때로 그렇습니다. 때로는 클라이언트를 위해 백그라운드 작업이 시작될 수도 있습니다. 읽기/쓰기는 간단한 조작을 의미하는 것이 아니라 DataManager와 클라이언트 간의 복잡한 통신 프로토콜을 따르는 것을 의미합니다. 클라이언트 요청은 토큰을 사용할 수있을 때까지 차단 될 필요는 없지만 때로는 적극적으로 거부됩니다. 혼란을 피하기 위해 SyncToken을 제안했습니다. 작성자는 SyncToken을 빌려야하고 returnSyncToken (unique_ptr )을 호출해야합니다. –