목록Categories (1099)
KoreanFoodie's Study
[C++ 게임 서버] 1-7. SpinLock 핵심 : 1. SpinLock 은 Lock 을 잡기 위해 '무작정 기다리는' 방식이다. 2. SpinLock 은 atomic 변수와 lock, unlock 함수로 쉽게 만들 수 있다. compare_exchange_strong 함수를 기억하자. 3. SpinLock 은 불필요한 CPU clock 을 낭비하지만, 때로는 컨텍스트 스위칭에 드는 것보다 비용이 저렴할 수도 있다. 이제 본격적으로 SpinLock 을 구현해 보자. SpinLock 은 간단하다. 그냥 Lock 을 잡을 때까지 무작정 While 문을 돌면서 기다리도록 만들 것이다 🤣 간단하게 생각하면 아래와 같이 구현하겠지만... int sum = 0; class SpinLock { private: b..
[C++ 게임 서버] 1-6. Lock 구현 이론 핵심 : 1. Lock 을 구현하는 방식은 크게 세 가지로 나뉜다. 무작정 기다리기, 잠시 후 돌아오기, 깨워줄 때까지 기다리기 2. SpinLock 을 사용하여 무작정 기다리거나, 어느 정도 Sleep 을 하고 난 후 Lock 을 다시 잡으려고 시도할 수도 있다. 3. 혹은 다른 일을 하다가, Lock 을 잡을 수 있게 되는 상태가 되었을 때 노티를 달라고 요청할 수도 있다. 예를 들어 Condition Variable 이 있다. 이 과정에서 컨텍스트 스위칭이 일어날 수 있다! 본격적으로 Lock 을 구현하기 전, Lock 을 구현하는 일반적인 방식 3 가지에 대해 먼저 소개하고 가도록 하겠다. 사실 내용은 간단하다. Lock 이 이미 걸린 상태라고 할..
[C++ 게임 서버] 1-5. DeadLock 의 개념과 기초 (+ std::lock) 핵심 : 1. DeadLock 상황은, 여러 쓰레드들이 Lock 을 서로 잡고 있어 풀거나 새로 잡지 못하는 교착 상태를 의미한다. 2. DeadLock 상황은 Lock 을 잡는 순서를 잘 조절하거나, 적절한 Lock 을 사용하여 회피할 수 있다. 3. std::lock 은 여러 개의 Lock 을 DeadLock 없이 한꺼번에 잡을 수 있도록 도와준다. 다음과 같이, Lock 이 2개 존재하고 연산을 위해 Lock 2 개를 전부 잡아야 한다고 가정하자. int sum = 0; mutex mutexAdd; mutex mutexSub; void Add() { for (int i = 0; i < 1000; ++i) { mu..
[C++ 게임 서버] 1-1. 멀티쓰레드 개론 핵심 : 1. Critical Section 에 진입할 때는 mutex 등을 활용하여 Lock 을 걸면 Race Condition 을 해소할 수 있다. 2. 일반적으로 직접 lock/unlock 을 해주기 보다, lock_guard 나 unique_lock 을 사용하여 RAII 방식으로 Lock 을 걸어 주는 것이 좋다. 3. unique_lock 의 경우, defer_lock 등의 옵션을 주어 Lock Guard 를 좀 더 유연하게 사용할 수 있다. 다만 lock_guard 에 비해 메모리를 더 많이 차지하고 무거을 것이다. 다음과 같이 여러 쓰레드를 이용해 벡터에 원소를 삽입한다고 해 보자 : vector vec; void Push() { for (int..
[C++ 게임 서버] 1-3. atomic 에 대하여 핵심 : 1. ++, -- 같은 간단한 연산조차, 사실 어셈블리어에서는 '값 복사' -> '복사된 값에 연산 수행' -> '복사된 값을 다시 대입' 같은 과정으로 쪼개진다 2. 만약 특정 연산이 진행 중일 경우, 다른 연산이 끼어들지 않도록 만들고 싶다면, 해당 변수를 atomic 으로 선언할 수 있다. 3. 일반적으로 atomic 연산은 일반 연산보다 느리므로, 남용은 지양하여야 한다. 어떤 연산이 atomic (원자적) 으로 이루어진다는 것은, 해당 연산이 진행되는 중간에 다른 연산이 동시에 진행되지 않는다는 것을 의미한다. 이전에 여러 쓰레드들이 공유 자원에 접근하려 할 때 Race Condition 이 발생할 수 있다고 이야기한 적이 있는데, ..
쓰레드 생성 핵심 : 1. 쓰레드를 생성하는 방법은 간단하다. 그냥 std::thread 에 알맞은 함수를 넣어주기만 하면 된다. 2. 쓰레드를 닫아줄 때는 join 으로 닫아주면 된다! 닫기 전, joinable 로 join 가능한지를 체크한다. 3. 쓰레드 객체 생성 시, 함수의 인자에 맞게 갯수를 넣어주어야 잘 동작할 것이다. 쓰레드 객체 생성자 내부는 가변 길이 템플릿으로 구현되어 있다. 이제 쓰레드를 생성하는 기초적인 실습부터 진행해 보자 😂 #include "pch.h" #include #include "CorePch.h" #include #include #include #include using namespace std; void HelloThread() { cout
[C++ 게임 서버] 1-1. 멀티쓰레드 개론 핵심 : 1. 멀티쓰레드 프로그래밍은 식당을 운영하는 것과 비슷하다. 테이블을 프로세스, 테이블에서 일하는 직원을 쓰레드, 영혼을 코어라고 생각하면 편하다. 2. 쓰레드는 힙 영역을 공유하지만, 각각의 정보를 스택에 저장한다. 따라서 힙 영역에 접근할 때는 Race Condition 이 발생할 수 있다. 멀티쓰레드 프로그래밍은 식당을 운영하는 것과 비슷하다. 테이블을 프로그램, 직원을 쓰레드, 영혼을 CPU 코어라고 생각하자. 그럼 영혼이 직원에게 들어가야 프로그램이 돌아갈 것이다. 이제 우리가 해야 할 일은, 영혼을 직원에게 어떻게 분배해야 좋을지 구조를 설계하고 코드를 짜는 것이다! 실제로 위의 스샷처럼, CPU 코어를 적절히 배분하면서 생기는 문제를 잘..
[언리얼] 스크롤박스에서 왼쪽 클릭으로 드래그하기 핵심 : 1. UScrollBox 에서는 기본적으로는 오른쪽 클릭을 통해 잡아끌기(마우스 클릭으로 드래그) 가 가능하다. 2. 좌클릭으로 드래그를 활성화 하려면, 하위 위젯에 버튼을 넣고, 버튼에서 Click Method / Touch Method 설정을 각각 Precise Click, Precise Tap 으로 바꾸어 주면 된다. 3. 자세한 것은 영상 참조. UScrollBox 에서 좌클릭으로 스크롤을 하고 싶으면, UScrollBox 아래에 버튼을 만들고, 버튼의 속성을 위와 같이 변경해 주면 된다. 참고로, Horizontal 하게 아이템을 담을 때는 WrapBox 를, Vertical 하게 아이템을 담을 때는 VerticalBox 를 UScrol..
[언리얼] UnrealVS 로 메모리 이슈 예방하기 (-stompMalloc) 핵심 : 1. Stomp Allocator 로 잠재적인 메모리 이슈를 잡아낼 수 있다. 2. 바인딩을 꼬리물기처럼 만들면 안된다(상위 > 중위 > 하위 위젯 순으로 열리는 경우, 같은 타입의 델리게이트가 바인딩되면 안됨) 3. stompmalloc 은 실제 가상 메모리 대신 물리 메모리 주소에 할당/해제 작업을 직접적으로 하도록 도와준다. 게임을 다 만들고 나서 실행을 했는데, 자꾸 크래시가 나서 게임이 꺼져버리면 매우 허망할 것이다. 특히 메모리 이슈의 경우, 정확히 어디서 메모리가 오염되었는지 개발 단계에서는 파악하기가 매우 어렵고 테스트 비용이 큰 편이다. 메모리 이슈를 디버깅하기 위한 좋은 방법이 하나 있는데, 바로 U..
언리얼에서 TMap 에 Compare Functor 지정하기 핵심 : 1. C++ 에서는 Functor class 를 넣어 주기만 하면 된다. 2. TMap 에서는 TMap 자체가 그냥 unordered_map 이라 그런 건 없다. 만약 Predicate 를 지정하고 싶으면, TSortedMap 을 사용하자! 3. TMap 을 정렬할 때는 Sort 를 사용하자... 후... C++ 에서는 TMap 에서 Key 값을 이용한 정렬을 역순으로 하고 싶을 때, std::less 나 std::greater 같은 predicate 클래스를 사용했다. 혹은 아래와 같이 Functor class 를 만들어 3번째 인자에 넣어 주기만 하면 되었는데... #include #include #include class MyCo..