목록Categories (1110)
KoreanFoodie's Study
[언리얼] UI 에서 애니메이션의 이벤트가 끝났음을 알려주는 방법 핵심 : 1. UI 에 삽입된 애니메이션에서 이벤트를 추가하고, 그래프에서 이벤트가 발생했을 때 호출할 함수를 C++ 에서 검색해서 연결해 주면 된다. 가끔 그런 경우가 있다. 코드로 풀어야 하는 동작과 연출을 함께 사용해야 할때, 특정 동작을 연출이 끝나는 타이밍에 의존해야 하는 경우가. 대표적으로 애니메이션이 있는데, 애니메이션이 완전히 끝나거나, 특정 시점에 왔을 때 코드에서 특정 동작을 수행하도록 만들어야 하는 케이스가 왕왕 생기곤 한다. 보통 스킬 쪽 구현을 하다보면, Notify 같은 걸 만들어서 이를 해결하기도 하지만.. UI 의 경우에는, 이벤트 트리거를 통해 이를 해결할 수 있다. 이제 예시를 보자. 일단 원하는 UI 를 ..
[C++ 게임 서버] 2-5. STL Allocator 핵심 : 1. STL 자료구조에서 사용하는 allocator 대신, 우리가 직접 만든 STL Allocator 를 적용한 커스텀 STL 을 만들어 보자. 2. STL Allocator 는 allocate 와 deallocate 함수만 정의해 주면 되며, STL 특수화에서 Allocator 의 인자를 우리가 만든 STL Allocator 로 바꿔치기해주기만 하면 된다! 우리는 지난 시간에 Stomp Allocator 를 구현하면서, 메모리 할당/해제를 커스터마이징 할 수 있다는 것을 알게 되었다. 그리고 한 발 더 나아가서, 사실 STL 자료구조(vector, queue 등)을 이용할 때도, 우리가 직접 만든 allocator 를 사용할 수 있다! 이..
[C++ 게임 서버] 2-4. StompAllocator 핵심 : 1. 프로그램은 가상 메모리를 사용하므로, 메모리 오염이 즉각적으로 발견되지 않을 수도 있다. 2. StompAllocator 를 사용하면, 할당 및 해제 시 '실제로' 메모리의 할당과 해제가 일어나므로, 메모리 오염으로 인한 문제를 즉각적으로 발견할 수 있다(alloc 은 '예약' 상태밖에 사용안함). 3. PageSize 와 Granularity 등의 개념을 잘 알아두자. 일반적으로 기본 PAGE_SIZE 는 4KB, Granularity 는 64KB 이다. 이전에 언리얼 엔진과 관련된 테스트를 진행할 때, UnrealVS 를 이용해 '-stompmalloc' 테스트를 하는 내용을 포스팅한 적이 있었다. StompAllocator 를 ..
[C++ 게임 서버] 2-3. Allocator 핵심 : 1. C++ 에서는 new 와 delete 도 오버로딩할 수 있는데, Allocator 를 만들어 커스텀화된 new 와 delete 를 사용해 보자! 2. placement new 기법을 이용하면, 내가 지정한 메모리에 객체를 초기화할 수 있다! 놀랍게도(?) C++ 에서는 new 와 delete 를 오버로딩하여, 메모리 관리를 섬세하게 커스터마이징할 수 있다. static void* operator new(size_t size) { cout
[C++ 게임 서버] 2-2. 스마트 포인터 핵심 : 1. 스마트 포인터에는 3종류가 있다. unique_ptr, shared_ptr, weak_ptr. 이 중, unique_ptr 는 소유권 개념을 위한 간단하고 가벼운 스마트 포인터이다. 2. shared_ptr 를 생성하면 사용하고자 하는 타입에 대한 메모리와 참조 카운트 등을 관리하는 제어 블록(Control Block)에 대한 메모리가 둘 다 할당된다. shared_ptr 의 경우 순환 문제가 발생할 수 있으므로, 주의해야 한다! 3. shared_ptr 에 대한 참조 횟수가 사라지면 우리가 사용하고자 하는 데이터에 대한 메모리는 해제되나, 만약 해당 포인터를 참조하는 weak_ptr 가 있을 경우, 제어 블록은 해당 포인터를 참조하는 weak_..
[C++ 게임 서버] 1-25. Reference Counting 핵심 : 1. 멀티 쓰레드 환경에서, 생 포인터를 사용하는 것은 언제나 위험하다. 의도치 않게 delete 된 포인터를 사용하려고 할 수도 있기 때문이다. 2. 일반적으로는 Smart Pointer 를 통해 이런 문제를 해결하는데, 핵심적인 부분은 결국 Reference Count 를 체크하여 nullptr 에 접근하는 것을 막는 것이다! 물론 SharedPtr 까지 제대로 써 주어야 문제를 막을 수 있다. 멀티쓰레드 프로그래밍을 할 때, 생 포인터를 사용하게 되면 의도치 않게 nullptr 에 접근하는 경우를 맞딱뜨리게 된다. 아래의 예시를 보자. 레이스와 터렛이 있다고 하고, 터렛이 레이스를 타겟팅하여 격추 시키는 것을 상상해 보자! ..
[C++ 게임 서버] 1-24. 연습문제 (소수의 갯수 구하기) 핵심 : 1. 연습문제를 풀어보자... (주어진 숫자까지의 소수의 갯수 구하기) 2. 쓰레드 혹은, future 를 통해 구현할 수 있다. 3. thread::hardware_concurrency() 를 이용해, 실제 코어 갯수만큼 쓰레드를 생성하는 것이 더 효율적일 수 있다(그보다 훨씬 많이 생성하는 것보다). 이제 연습문제를 풀어보자. 주어진 숫자에 대해, 1부터 해당 숫자까지 소수의 갯수를 구하는 문제이다. 일단 멀티 쓰레드를 이용할 것이니, 각 쓰레드에 태워 보낼 함수를 다음과 같이 정의하자 : bool IsPrime(int InInput) { if (InInput
[C++ 게임 서버] 1-23. DeadLock 탐지 핵심 : 1. 데드락을 잡는다는 것은, 결국 락을 잡는 방식에 있어 사이클이 형성되는지를 판단하는 것과 동일하다. 2. DFS 를 응용하여, 사이클이 생기는지 여부를 검사하면 DeadLock 상황을 미리 검출할 수 있다. DeadLock 의 경우, 개발 단계에서는 나오지 않으나, 막상 라이브 서비스를 하면 검출되는 경우가 많다. 구조적으로는 데드락이 걸릴 로직이 있음에도, 접속자 수가 많지 않아 데드락이 걸리지 않을 수 있다. 이런 타이밍 적인 이슈에 의존하지 않고, DFS 방식으로 사이클이 있는지를 검사하여, 데드락 문제를 미리 방지할 수 있다. 데드락을 잡는다는 것은, 결국 락을 잡는 방식에 있어 사이클이 형성되는지를 판단하는 것과 동일하기 때문이..
[C++ 게임 서버] 1-22. Reader-Writer Lock 핵심 : 1. 읽는 경우가 쓰는 경우보다 훨씬 많을 경우, Read Lock 과 Write Lock 을 나누어서 사용할 수도 있다. 2. Write Lock 의 경우 쓰레드의 ID 를 기준으로 소유권을 경합하고, Read Lock 의 경우 공유 카운트를 올리는 방식으로 작동한다. 3. Write Lock 을 잡은 상태에서 Read Lock 을 잡는 것은 가능하지만, Read Lock 을 잡은 상태에서 바로 Write Lock 을 잡는 것은 불가능하도록 설계한다. 만약 어떤 컨텐츠에서, 내용을 읽는 경우는 1초에 100번 일어나는데, 실제로 내용을 쓰는 경우는 일주일에 한 번 일어난다고 가정해 보자. 이때, 사실 내용을 읽을 때마다 쓰레드별..
[C++ 게임 서버] 1-21. ThreadManager 핵심 : 1. Thread 를 직접 생성하기보다, ThreadManager 를 통해 생성해 보자. 2. ThreadManager 를 통해 쓰레드를 관리하면, 초기화 및 종료 시점의 작업을 자동화시킬 수 있을 것이다. 3. CRASH 관련 매크로를 유용하게 활용하자. 이제 본격적으로 서버 구축을 시작하기 전에, Thread 관리를 도와줄 ThreadManager 를 만들어 보도록 하겠다. 원리나 기능은 간단하다. 현재로서는 Thread Local Storage 에 각 쓰레드별로 ID 를 부여하고, 생성시에 이를 출력하는 정도의 기능만 만들 것이다. 코드를 보면 이해가 빠르다. ThreadManager.h #pragma once #include #in..