전체 글 143

TLS(Thread Local Storage)

TLS란 쓰레드마다 가지고 있는 로컬 저장소 이다. 이러한 저장소가 필요한 이유를 알아보자. 여러 쓰레드가 힙에 저장된 특정 변수를 참조하는 상황을 생각해보자. 이러면 하나의 공유 변수를 참조하기 위해 여러 쓰레드가 경합을 벌이게 된다. 즉 하나의 쓰레드가 참조하고 있으면 다른 쓰레드는 기다려야 한다는 뜻이다. 하지만 이때 만약 쓰레드마다 자신의 저장공간이 있고 그 공간에 공유 변수를 가져다 놓고 연산을 한다면 경합으로 인한 성능 저하를 피할 수 있을 것이다. 스택과 다른 점 : 스택은 함수를 위한 저장소이다. 계속 할당됐다 해제됐다를 반복한다. TLS는 쓰레드마다 영구적으로 데이터를 보관하는 용도로 사용한다. 스택은 영구적으로 뭔가를 저장하기엔 안좋음. 예시 //_declspec(thread) int3..

C++ 2022.02.01

메모리 모델

복습 Race Condition (경합 조건): 여러 쓰레드가 동일한 메모리에 동시 접근할 때 발생. write가 문제임. Undefined Behavior가 발생함. 해결법 : Lock, Atomic C++이 보증하는 기본 원칙 : atomic 연산에 한해 모든 쓰레드가 동일 객체에 대해 동일한 수정 순서를 관찰한다. 이게 무슨 소리인가? atomic 연산 동일 객체란 그냥 하나의 메모리 공간, 변수 쯤으로 생각하면 된다. 동일한 수정 순서란 atomic:: is_lock_free() //lock을 걸 필요 없음(원자적으로 수정됨) true : 원자적 수정. false : 원자적 수정 안됨. atomic의 메모리 정책 메모리 정책에 따라 가시성, 코드 재배치 문젲가 해결되거나 안되거나가 결정됨. 메모리..

C++ 2022.02.01

Futrue

c++ 11에 공식적으로 추가된 내용. #include 동기방식 synchronous : 오래 걸리면 비동기로 하는게 좋다. 조금 오래걸리는 함수 한 번만 실행할건데 그걸 가지고 스레드를 만드는건 좀 낭비같다는 생각이 든다. 즉1회성 이벤트에 유용하다. 이런 상황에서 가볍게 실행가능한 것이 future 이다. 말하자면 '애기 스레드 만들기' 라고 할 수 있다. std::future future = std::async(std::launch::async, Calculate); //async는 defered라는 선택지도 있음. std::future future = std::async(std::launch::async, &Knight::GetHp, knight1); // 함수가 멤버함수일 경우 이렇게 씀. in..

C++ 2022.01.27

조건 변수(Condition Variable)

이전 글에서 멀티쓰레드 이벤트 LOCK 에 대해 알아봤다. https://ddukddaksudal.tistory.com/62 멀티 쓰레드 Lock 구현 Lock 상태일 때 다른 쓰레드는 뭘 할까? 어떤 쓰레드가 lock을 하고 메모리를 차지했다면 다른 쓰레드들은 unlock될 때 까지 기다려야 한다. 그런데 기다린다는 것은 말하자면 시간 낭비이다. 어떻게 ddukddaksudal.tistory.com 그런데 이러면 이벤트와 lock 코드가 분리되어 있기 때문에 쓰레드가 원하는대로 동작하지 않을 수 있다. 예를 들어 handle이 signal 상태가 되어 WaitForSingleObject함수를 탈출하고 lock을 얻으려고 했는데 그 사이에 다시 다른 쓰레드가 lock을 걸어버릴 수 있다는 것이다. 이 문..

C++ 2022.01.27

멀티 쓰레드 Lock 구현

Lock 상태일 때 다른 쓰레드는 뭘 할까? 어떤 쓰레드가 lock을 하고 메모리를 차지했다면 다른 쓰레드들은 unlock될 때 까지 기다려야 한다. 그런데 기다린다는 것은 말하자면 시간 낭비이다. 어떻게 시간 낭비를 줄일 수 있을지 몇 가지 정책을 알아보자. Spin Lock : unlock 될 때까지 무작정 기다리기 Sleep : 일단 물러나고 나중에 다시 돌아오기.(랜덤) Event : 다른 사람한테 unlock 되면 알려달라고 하고 나는 다른일 하고 있기. 대표적으로 위와 같은 정책들이 있다. 아니면 일정 시간 무작정 기다리다가 물러나기 와 같이 위 정책들을 적절히 섞어 써도 된다. 그렇다면 위 정책을 사용하려면 Lock 함수를 어떻게 구현해야 할지 알아보자. Spin Lock lock이 풀릴 때..

C++ 2022.01.26

멀티 쓰레드

c++ 11 이후 에선 #include , std::thread(쓰레드함수) 로 Windows 환경에 종속적이지 않은 멀티 쓰레드를 구현할 수 있다. 엔트리 포인트 : 쓰레드 함수 자식 쓰레드 t가 종료되기 전에 메인 쓰레드가 먼저 종료되면 에러가 뜸. 디버그 시 각 쓰레드별 실행중 문장 확인 가능. 쓰레드 주요 함수들 t.hardward_concurrency() : CPU 코어 갯수 t.get_id() : 쓰레드의 id t.detach() : 쓰레드 객체 t와 실질적으로 동작하는 쓰레드의 연결을 끊어버림. 데몬 프로세스. t.joinable() : t 객체에 실질적으로 연동된 쓰레드가 있는지 확인 = 쓰레드 id가 0인지 확인. (연동된 쓰레드가 없다면 쓰레드 id는 0이 됨) t. join() : 자..

C++ 2022.01.24

경로 설정

경로 설정 팁 : $(SolutionDir) 는 sln 파일이 있는 디렉터리의 경로이다. $(Configuration)는 현재 빌드 환경( Debug, x64 등) 에 따라 달라지는 경로이다. 이것은 일반 매크로 라고 하나보다. 아래 링크에 가면 매크로가 어떤 의미를 갖는지 볼 수 있다. 또한 프로젝트 속성 등 설정할 때 나오는 '>>매크로' 이런 버튼을 누르면 모든 일반 매크로가 어떤 경로를 지정하고 있는지 볼 수 있따. https://docs.microsoft.com/ko-kr/cpp/build/reference/common-macros-for-build-commands-and-properties?view=msvc-170 MSBuild 명령 및 속성에 대한 일반 매크로 자세한 정보: MSBuild 명..

Visual Studio Tip 2022.01.23

미리 컴파일된 헤더

미리 컴파일된 헤더란? pch 파일의 내용들을 미리 컴파일 해두고 다음 컴파일 때마다 미리 컴파일된 내용을 사용하는 것이다. 여러 파일에서 자주 쓰는 헤더들을 여기에 포함시켜서 미리 컴파일 해놓은 다음, 다른 파일에서 pch.h를 사용하는 식으로 사용한다. 이렇게 하면 pch에 들어있는 헤더들을 매 번 컴파일 하지 않아도 되기 때문에 컴파일 시간이 매우 줄어든다. 그러나 만약 pch에 들어있는 내용이 바뀌게 되면 이 pch를 포함하는 모든 파일들에게 영향을 주게된다. 추가로 미리 컴파일된 헤더는 주로 pch 혹은 stdafx 라는 이름을 주로 가진다. 이름만 다르지 사실상 똑같은 역할인듯 하다. 사실 이름이 pch나 stdafx가 아니어도 된다. 또한 그냥 일반 파일을 미리 컴파일된 헤더로 만들 수도 있..

Visual Studio Tip 2022.01.23

웹 서버 vs 게임 서버

서버를 식당에 비유해본다면 웹 서버는 테이크아웃 식당, 게임 서버는 일반 식당에 비유할 수 있다. 테이크아웃 식당은 손님에게 음식을 주고 보내면 그 후로는 연락이 끊겨버린다. 일반 식당은 손님이 머물면서 식사를 하고 그 동안 직원과 손님이 실시간 교류가 있다. 웹서버 : 손님에게 먼저 접근할 일이 없다(stateless ). 웹 서비스 만드는데 사용, 프레임워크 골라서 사용., Spring, Nodejs 등 게임 서버 : 실시간 상호작용, 언제든 손님에게 접근 가능해야함. 손 님이 있는 동안 최상의 서비스 제공(Stateful) 게임 서버는 게임 장르, 형태에 따라 요구사항이 매우 다르기 떄문에 정형화된 프레임워크가 존재하기 힘듦. 제작 고려사항 최대 동시 접속자, 게임 장르 및 채널링, 게임 로직, 네..