목록분류 전체보기 (162)
Coding Memo
문제 서버 코어를 만들고 빌드를 하여 dll 파일을 생성했다. 이 dll 파일을 Unity에서 그대로 사용하려고 넣어서 컴파일을 했다. 물론 문제가 없었다. 하지만, 서버 코어에 있는 추상 클래스를 상속받아서 클래스를 하나 작성하려고 했는데 참 보기에는 어이없는 에러가 나타났다. CS0115: 재정의할 적절한 메서드를 찾을 수 없습니다. CS0534: 상속된 추상 맴버를 구현하지 않습니다. CS0115는 override 키워드가 적절하게 사용되지 않았을 때 (재정의할 메서드를 찾지 못했을 때) 나타나는 오류이고, CS0534는 추상 클래스를 상속 받았을 때, 반드시 구현해야 하는 맴버를 구현하지 않았을 때 나타나는 에러이다. 그래서 내가 구현을 안했을까? 난 구현했는데 계속 에러가 나타난다! 좀 더 간단..
Serilog는 멀티스레드 환경에서 별도 lock 컨트롤 없어도 괜찮은지 확인해보려고 한다. (기본적으로 Serilog는 thread-safe 하다고 한다.) 10개의 쓰레드 생성 각 쓰레드 마다 1000개의 로그 기록 => 총 n값이 10000까지 출력이 되어야 하고 n 값이 중복되서는 안된다. 다음 함수를 쓰레드로 실행시킬 것이다. n은 static으로 선언해서 별도의 lock 처리 없이 Information (및 Verbose, Debug, Error, Fatal)에서 ++n이 잘 실행되는지도 확인해보겠다. 추가적으로 운좋게(?) 경합이 일어나지 않아 예상대로 출력될 수도 있으니 3번씩은 실행시켜보았다. static int n = 0; static void Thread1() { for (int i ..
lock과 spinlock은 모두 멀티스레드 환경에서 공유 자원을 컨트롤하기 위한 동기화 메커니즘이다. 한 스레드가 접근 중일 때는 다른 스레드들은 대기하게 된다. 그렇다면 각각 어떤 특징이 있고, 어떤 상황에서 둘 중 무엇을 사용해야 더 성능면에서 유리하게 사용할 수 있을지 알아보았다. 대기 방식 - lock: 락을 얻을 때까지 대기를 하고, 대기하는 동안 CPU 자원을 사용하지 않음 - spinlock: busy-waiting 방식으로 다른 쓰레드가 락을 해제할 때까지 계속 루프를 돌면서 기다리고 이 대기 동안에 CPU를 계속 사용함 이 외에는 크게 의미 있는 차이가 없는 것 같다. lock 방식은 CPU 자원을 많이 사용하지 않지만 lock을 얻고 해제하는데 다소 자원이 들어갈 수 있다. 반면에 s..
멀티 쓰레드 환경에서는 여러 쓰레드가 한번에 어떤 공유 자원(전역 변수, 맴버 변수 등등)에 접근하고 수정하려고 하면 매우 큰 문제가 발생할 수도 있다. 아래 코드의 실행 결과를 예상해보자. class Program { static int n = 0; static void Thread1() { for (int i=0; i
구글에서 제공하는 프로토버퍼를 이용해 서버와 클라이언트간 패킷을 주고받는 시나리오를 계획했다. 서버와 클라이언트 간 전송 시에는 byte[]라는 배열로 주고 받게 되는데, 이 배열을 다시 어떤 객체로 파싱하는 과정이 필요하다. CustomBuffer (직접 직렬화한 버퍼)를 사용하였을 때는 버퍼의 헤더를 추가하여, 버퍼의 맨앞에 2바이트 타입을 추가하고 그 값으로 전체 패킷의 길이를 넣었고 두번째 2바이트 값으로 해당 패킷의 원래 객체 타입을 정의해서 넣었었다. 아래의 구조와 같이 직렬화하는 버퍼를 CustomBuffer라고 하겠다. 파싱할 때는, 처음 2바이트를 읽어서 단위 패킷의 범위를 정한다. 그 다음으로 2바이트를 읽어서 Body에 있는 데이터를 어떤 객체로 역직렬화할 건지 알아낸다. 마지막으로,..
C++에서 상수를 정의하는 방법으로 2가지가 있다. 첫 번째로, define을 이용하여 매크로로 상수를 정의하는 방법이 있고, 두 번째로는 constexpr을 이용하여 상수를 정의하는 방법이 있다. #define PI 3.141592 constexpr double PI = 3.141592; 두 방법의 특징과 차이점을 보고 무엇을 사용하면 더 좋을지 확인해보자. define define은 전처리기(preprocessor) 지시자로, C++의 전처리기를 통해 상수를 정의하는 방법이다. 이는 매크로를 이용하는데, 매크로는 컴파일 전에 사용된 매크로값이 텍스트 치환을 통해 해당 정의 내용으로 그대로 바뀐다. (말 그대로 매크로 값에 정의했던 내용이 그대로 들어간다. 단순히 텍스트 치환 기능이다.) define의..
vector, deque, set, map, stack, queue, priority_queue 등의 컨테이너와 자료구조에서 자주 사용하는 함수들을 간단하게 요약하였다. 먼저, 간단하게 표현하기 위해서... 편의상 템플릿 타입과 컨테이너 사이즈 타입(size_t)은 int 형으로 하였다. 템플릿 타입 명시 를 생략하였다. const를 생략했고 각 컨테이너의 iterator는 간단하게 iterator로만 표현했다. 진짜 진짜 주요한 함수만 확인해보려면 스크롤을 맨 아래로 내리자! 참조: https://en.cppreference.com/w/cpp/container vector Sequence Container로 요소에 대해 순차적으로 접근 할 수 있다. (forward, backward 둘 다 순회 가능)..
흐름 제어란? 발신자가 수신자가 처리할 수 있는 것보다 더 빨리, 많이 데이터를 보낼 경우에 수신자는 일부 데이터(패킷)에 대해 삭제가 되거나 손실이 발생 할 수 있다. 이 문제를 방지하기 위해 TCP 연결에서는 흐름제어를 사용한다. 흐름제어(flow-control)는 수신자의 상태를 보고 전송을 제어하여 데이터의 손실이나 정체 없이 효율적이고 안정적으로 통신을 가능하게 한다. 예를 들어, 수신자가 100바이트의 버퍼를 가지고 있는데, 발신자가 150바이트의 데이터를 보냈다고 가정하자. TCP 연결에서 발신자는 수신자가 처리 할 수 있는 데이터의 양 (Sliding Window)을 미리 정한다. 따라서 발신자는 먼저 100바이트를 송신하고, 수신자가 먼저 100바이트를 받고 처리 후, 발신자에게 추가 데..