게시글
질문&답변
보편참조 관련 질문
저도 같은 부분에 궁금증을 가져서 삽질해본 결과 그나마 합리적인 추측을 할 수 있었습니다. 1. Job 생성자의 마지막 인자 Args&&... arg는 보편 참조가 아닙니다. 그 이유는 앞선 두 번째 인자인 Ret(T::* memFunc)(Args...) 에서 Args가 먼저 추론되고 이후 마지막 인자인 Args는 추론이 되지 않습니다. (non-deduced) 즉, 이미 추론된 타입에 &&가 붙게 됩니다. 이 말은 마지막 인자는 항상 rvalue reference가 된다는 의미이죠.2. std::forward는 템플릿 인자 T에 참조가 붙지 않으면 rvalue로 캐스팅하여 리턴해줍니다. PushJob의 정의를 보면 Args는 보편참조가 아닌 일반 lvalue만을 받는 템플릿 형식입니다. 여기서 받은 비참조 타입 lvalue를 forward를 통해 rvalue로 캐스팅한 후 MakeShared에 넘겨주고, 이 안에서는 계속 perfect forwarding을 통해 값 카테고리를 보존한 채 placement new(생성자 호출)까지 도달하게 됩니다.아마 테스트에서 std::forward(player)를 Job 생성자에 바로 넣어주면 똑같이 컴파일 에러가 나올겁니다.3. 1번의 답변과 일맥상통 할 것 같습니다. 저는 이와 같이 이해하고 넘어가려 하며 정확하지 않은 정보일 수 있으니 더 정확한 정보를 위해서는 cppreference의 템플릿 추론 규칙 아티클이나 모던 c++의 템플릿 추론 챕터를 읽어보는 것을 추천드립니다!
- 1
- 1
- 155
질문&답변
Lock-Free Stack #2 강의 질문
저도 비슷한 생각을 했었는데 생각을 좀 정리해본 결과 이러한 상황을 고려해보면 될 것 같습니다.Node* OldHead = Head.load(); while (OldHead && !Head.compare_exchange_weak(OldHead, OldHead->Next)) {};두 스레드가 같이 pop함수에 들어온 상태라고 했을 때, 먼저 한 스레드가 oldHead를 획득하고 카운팅을 하지 않고 이 oldHead를 삭제한다고 해봅시다. 그런데, 삭제하기 전에 이미 획득한 스레드 말고 다른 스레드가 같은 Head를 참조하여 같은 oldHead를 획득한 상태라고 하고, 이후 다른 스레드에서 이것을 삭제하고 나머지 스레드가 뒤늦게 CAS 함수를 호출한다면 OldHead->Next에서 크래쉬가 날 것 같습니다.즉, 1. Node* oldHead = _head 줄을 거의 동시에 진행하여 같은 oldHead를 획득한 스레드가 두 개가 있다. (PopCount 2개)이 때 한 스레드가 CAS를 통과하고 매우 빠르게 삭제를 했는데 이와 동시에 나머지 스레드가 CAS를 들어간다면, 이 아디리가 터진다면 크래쉬가 발생한다. (거의 동시에 들어왔지만 한 쪽은 CAS를 통과하고 delete하는 동안 다른 한 쪽은 가만히 있다가 이제서야 CAS를 시도하는 이 아다리가 무수히 많은 스레드에서 낮은 확률로 발생하지 않을까..? 싶습니다)
- 1
- 1
- 216
질문&답변
WaitForSingleObject의 Auto reset 처리는 원자적인가요
이 질문을 보고 저도 정확한 답변이 궁금하여 제 생각좀 끄적이고 갑니다.아예 틀린 생각일 수 있으니, Rookiss 선생님의 공식 답변을 기다리며 그냥 흘러넘기듯 보시면 될 것 같습니다!제가 이해한 바로는, WaitForSingleObject()를 사용하는 것은 이벤트를 만들 때 부여받은 handle의 이벤트를 참조하여 signal state를 확인하는 것으로 이해했습니다. 즉 인자로 넣어준 handle 이벤트의 state를 확인하여 시그널이 켜져 있는지 확인 후 리턴 값을 보내주는 것 같습니다. 리턴 값들은 공식문서를 보면 잘 나와있습니다.결국 프로듀서 스레드가 SetEvent()를 호출하면, 커널은 인자로 넣어준 이벤트 handle을 참조하여 커널단에서 이 시그널 state를 켜주는 것으로 보이고, 컨슈머 스레드는 WaitForSingleObject()로 이 시그널을 확인하고 켜져있다면 모드를 확인 후 이벤트의 시그널을 다시 꺼주고 리턴 값을 리턴해주는 것 같습니다. 즉, 스레드의 교착상태와 관계없이 커널단에서 생성된 이벤트 풀? 큐? 아님 그냥 단일 이벤트? 의 상태들을 커널이 함수들(시스템 콜)이 호출될 때마다 바꿔주는 것 같습니다. 결국 커널이 시스템 콜을 요청 받았을 때 이벤트의 상태를 바꿔주고 뿌려주는 것이기 때문에 스레드 측면에서 이 처리가 원자적인지 데드락이 걸리는지 확인할 필요가 없다고 생각합니다. 이러한 시스템 콜 때문에 스핀락 같은 기법보다 처리는 깔끔하지만 그만큼 오버헤드를 더 먹는게 아닐까? 생각이 드네요.. (싱글오브젝트가 아닌 여러 스레드를 하나의 이벤트에 다중으로 등록하거나 등등)
- 0
- 3
- 273