오늘 작업 현황 (23. 02. 08)
- 쓰레드
- 크리티컬 섹션
- 함수 호출 규약
쓰레드
▩ 쓰레드
: 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위


▩ 쓰레드 관련 간단 설명
[ 쓰레드 동기화 ]
1. 실행순서의 동기화
: 쓰레드 실행 순서 정의, 순서에 반드시 따라야 함
2. 메모리 접근에 대한 동기화
: 메모리 동시 접근 불가, 한 순간에 하나의 쓰레드만 접근해야 하는 메모리 영역
[ 쓰레드 동기화 2가지 방법 ]
1. 유저 모드 동기화 - 크리티컬 섹션 기반의 동기화
2. 커널 모드 동기화
[ 크리티컬 섹션 = 임계영역 ] // Critical_section
- 메모리 영역의 접근 동기화 = 임계 영역의 접근 동기화
- 한 순간에 하나의 쓰레드만 접근을 요구되는 공유 리소스에 접근하는 코드 블럭
(ex. __stdcall LoadingMain이 아닐까)
[ 문제를 일으키는 코드 블럭인 임계 영역의 해결책 ]
: 동기화 기법을 통해서 임계영역의 동시 접근을 막는 것
▩ 크리티컬 섹션 기반의 동기화
: 화장실 들어가기 전 열쇠로 문을 열고, 다른 사람을 위해 화장실 앞에 열쇠를 두는 방식
=> 열쇠(=CRITICAL_SECTION)를 얻는 자만 화장실에 입장 가능(한 순간에 하나의 쓰레드만 접근)
1. 크리티컬 섹션 오브젝트(=열쇠) 생성
CRITICAL_SECTION m_CriticalSection 변수 생성
2. 크리티컬 섹션 오브젝트를 초기화하여 사용 가능한 상태로 만들어주기
InitializeCriticalSection(&m_CriticalSection);으로 초기화
3. 열쇠를 획득하기
EnterCriticalSection(&m_CriticalSection);
- 누군가 이미 이 함수를 호출(열쇠를 획득)한 상태라면 호출된 함수는 블로킹.
열쇠가 반환되면 블로킹 상태에 있던 함수는 빠져나옴.
임계영역으로 들어갔을 때 이 함수를 호출한 쓰레드가 열쇠를 획득함.
4. 열쇠를 다시 화장실에 걸어놓기
LeaveCriticalSection(&m_CriticalSection);
5. 초기화 함수 호출 과정에서 할당되었던 리소스 반환하기 (사용 불가능 상태로 만들기?)
DeleteCriticalSection(&m_CriticalSection);
CLoader
▩ CLoader
[ _beginthreadex(nullptr, 0, 쓰레드, 넘겨줄 값의 주소, 0, nullptr) ]
: 내부적으로 API를 호출하는 함수 (쓰레드 호출?)
- #include <Process.h> 필요 (현 위치 Engine_Defines.h")
- #define APIENTRY __stdcall
- 쓰레드(LoadingMain)은 전역함수로 멤버 변수를 가져올 수 없으므로
현재 _beginthreadex에서 &CLoader를 넘겨주어 Get으로 CLoader 안의 크리티컬섹션을 가져옴
- 크리티컬 섹션 초기화 후 _beginthreadex로 쓰레드 호출



▩ HANDLE 및 CRITICAL_SECTION 삭제

메모장 참고
_beginthreadex(nullptr, 0, 진입점함수, 진입점함수의매개변수, 0, nullptr);
APIENTRY 진입점 함수는 멤버 함수를 맘대로 쓸 수 없으므로
객체 자체의 주소를 받아옴
LoadingMain은 전역함수여서 멤버 못 씀
WaitForSingleObject( ~, INFINITE
인피니트 : 스레드가 완전히 끝날 떄까지
=> 스레드 함수가 return을 만날 떄까지
Loading Main은 생
로더는 만들려던 레벨의 메이 ㄴ스레드르 람ㄴ들어 호추
* 항상 로딩을 거쳐서 로딩 작업을 거치고 CLevel_Logo::Tick에서 넘어감
SetWindowText(윈창 제목);
메인 스레드 ? stdcall
서버 스레드? APIENTER
렌더를 위한 스레드는 만들면 안됨
디바이스는 어떤 스레드는 상관없는데
콘텍스트는 만들어낸 곳 제외하곤 스레드 돌리면 터짐
맵 컨테이너는 동적으로 쓰면 안된다.
=> 동적일 때 중간삽입을 하면 전체회전을 쫙 하는데 양이 많으니까 프레임 드랍
벡터는 동적으로 막 추가하지 말고 초기에 셋팅
리스트는 동적으로 추가
규약
언리얼 서밋, 유니티 스터디
* 로딩 시에 몬스터 원형ㅇ르 만들어놓고 게임 때는 만들어놓은 원형을
찾아서 쓰는 거 - 프로토타입 =(복사생성자 호출)
ASW, PlayFab 추천 (유니티기반), 뒤끝
몬스터 위치 지정 같은 것도 상수로정해주는 게 아니고 서버로부터 가져와야됨
- 그렇기에 우리는 현재는 상수로 해줬었지만 실제로 서버로 가져오기에 시간이 오래 걸림
그래서 로딩 때 미리 원형ㅇ르 만들어놓고 런타임 간에는
서버를 끊고 우리가 만들어둔 애를 복사해서 사용
Clone(void* )가 있는 이유는
아무 자료형이나 필요한ㄱ ㅓㄹ 넘겨줘야 하는 상황이 생길 때가 많아서 걍
GameObject_Manager은 1.원형 객체, 2.사본 객체를 관리 3. 사본 객체의 Tick 무한 호출
=> * 모아서 관리 : 내가 나누고 싶은 기준에 따라 레벨별로(Layer)
CLayer는 list<CGameObject>로 몬스터들을 우다다 저장
unordered map에서<이름, CLayer*> m_Layers[LEVEL_END];
는 이름은 몬스터, 환경물별로 저장, 그리고 배열로 레벨별로 관리
*** 레벨별로 분리하는 이유 ***
우리는 현재 Open_Level에서 다음으로 넘어갈 클래스를 만들어주고,
후에 기존 씬을 Safe_Release하는 형식이다.
즉, map에 넣어놓은 로고씬이 출력되고 있는 도중에
게임플레이씬 오브젝트들이 만들어져서 map에 넣어지고 있는 상황임
그래서 로고씬이 삭제되고 게임플레이씬으로 전환될 때
map에 들어있는 애 중에 로고씬 애를 구별해서 삭제해줘야함
-> 이게 극혐이니까 그냥 배열로 레벨들을 구분해서 해당 레벨 삭제하게해
=> 플레이어, 마우스처럼 계속 쓸것들은 레벨마다 지우고 삭제하면
기존 데이터들까지 유지해야되는 귀찮음이 있으니 LEVEL_STATIC 배열에 넣어주기
근데 엔진에선 클라의 enum을 쓸 수 없으므로 갯수를 정해줄 수 없어서
포인터로해서 동적으로 map* 으로 해주고 있음
* 먼저 호출, 나중에 호출은 tick에서 관리할 거임.
map으로 관리하는 게 아님.
* 원래 생성자 없으면 기본 생성자가 자동으로 생성되는데
헤더만 있으면 당연히 정의는 있어ㅑㅇ됨
[13. 쓰레드 동기화 기법] (tistory.com)
[13. 쓰레드 동기화 기법]
* 이 내용은 '뇌를 자극하는 윈도우즈 시스템 프로그래밍' 책의 내용을 정리한 것 입니다. 쓰레드 동기화란 무엇인가? 두 가지 관점에서의 쓰레드 동기화 여기서 말하는 동기화는, 순서에 있어서
popcorntree.tistory.com
'DirectX 기반 그래픽스 > 그래픽스 이론' 카테고리의 다른 글
| [DirectX] 셰이더에 리소스 전달 (ID3D11Effect) (0) | 2023.02.15 |
|---|---|
| [DirectX] 그래픽 파이프라인 - 입력 어셈블러(IA) 단계 (0) | 2023.02.13 |
| [그래픽스] 계층 구조 (0) | 2023.01.12 |
| [그래픽스] 충돌 검사 - 점과 점/선/평면과의 충돌 (0) | 2023.01.10 |
| [DirectX] 픽킹, 교차 판정 - 경계 구체와 반직선(광선) (0) | 2022.12.19 |