이 잡큐는 컨텐츠 딴에서 만들어도되고
ServerCore == 라이브딴에서 만들어도 노상관이다.
ServerCore -> Job 생성
그다음에 이 Job이라는 개념을 어떻게 만들어 줄 것인가가 고민이다.
만드는 방법은 여러가지인데 오늘 보여줄 것은 크게 두가지
1) C#문법을 사용하여 만드는것
2) 수동적으로 만드는 것
이 Job이라는 개념을 따로 파도되지만
일반적으로 C#에서 "어떤 행위"자체를
Action으로 표현하는 경우가 많다.
delegate를 이용해가지고 나중에 처리할 것들을
이런식으로 Action으로 밀어넣어주는게 일반적인 상황이다.
그래서 결국 잡큐라는것은 내가 해야할 "행동" == "Action"을
그냥 Queue로 들고있는게 잡큐이다.
그래서 상속을 받아주고
밑에 Action을 뱉어주는 Push, Pop을 lock을 걸고 만들어 주도록 하자.
두번째 고민
그러면 누가 Pop을 해서 사용을 하것인가??
(이것은 조금있다가 보도록 하자)
먼저 어떻게 사용을 할지 보자.
일단 > GameRoom rr
현재
이렇게 상속을 받고
지금 GameRoom이 이 밑줄 세가지 기능을 지원하는데
여기에 바로 접근을 해서 일을 하는게 아니라
이 각각의 행동들을 _jobQueue에다가 밀어 넣어가지고
진행을 할 것이다.
이렇게 한다음에
BroadCast, Enter, Leave사용하던데 수정을 ㄱㄱ
그래서 먼저 PacketHandler ㄱㄱ >
지금 이부분을 실행을 할게 아니라
Action으로 넘겨주기를 해야 한다.
그래서 Action으로 넘겨주는 가장 간단한 방법인 람다로 이렇게 해야할 행동을 넘겨주도록 하자.
그래서 이렇게 19번째 줄처럼 바로 해야 할일을 하러가는게아니라
"해야 할 일감"을 던져줘서 이 행동은 "주문서"처럼
Queue에다가 차곡차곡 쌓여가지고
어느시점에 쌓여있는 녀석들을 순차적으로 실행하면 될 것이다.
그런데 지금 문제가 살짝 있는데
Room이 null로 바뀌면 문제가 될 수 있다.
나중에 고치고 놔두자.
그다음 ClientSession ㄱㄱ >
이렇게 "내가 이렇게 할 일을 주문서 작성을 할테니 시간이 될때 이 "행동"을 처리를 해줘!" 라고 Push를 한셈이다.
OnDisConnected부분도 똑같이 해주도록 하자.
나중에 크래쉬가 날 것인데
일단은 이런 인터페이스를 사용을 할 것이다 정도만 알고 있어라!
그래서 다시 GameRoom으로 돌아와보면
여기 일감들이 쌓여있는데
이 "일감"들을 누가 어떻게 처리를 할것인가?? (ㄴㄱ 실행?)
ㄴㄱ? ->
1) 메인쓰레드 or 다른 쓰레드 순차적으로 돌면서 처리
2) 조금더 간단한 ㅂㅂ
Push를 할 때 맨처음으로 일감을 밀어 넣은 애라면은
실제로 "실행"까지 담당
그게 아니라면 그냥 Queue에다가 Push만하고 빠져나오는 방법
이렇게 있는데 비슷한 것을 전에 구현을 했었다.
일단, Session > ㄱㄱ
Session > Send에서
Queue에다가 sendBuff를 집어넣는데
if문 == 실제로 1빠로 와서 넣었다면 RegisterSend()의 실행까지 하고
1빠가 아니라면 Queue에다가 밀어만 넣고 빠져나오는 것임.
우리는 일단 Push를 하면서 Session > Send처럼 판별을 해주자.
Queue에 쌓인것을 실행 할 것인지 말것인지 정하는
_flush
만약
라면 Queue를 처리를 하면될 것이다.
그런데 실행을 할 때
이렇게 lock을 잡고 계속 실행을 하고 있으면
실행하는 동안 다른애들이 접근을 할 수 없으니까
강제적으로
이렇게 받아주도록 할 것이다.
그래서 _flush가 false라면은
"아하! 내가 이제 실행을 해야 겠구나!" 라는것을
flush = _flush = true로 받아주는 것이다.
그래서 true일 경우 "일을 처리 해야됨!"이니까
Flush라는 일을 처리를 할 함수를 만들어 주도록 하자.
그래서 if문으로 Pop()을 한다음에
일감을 뽑아와서 없다면 retrun -> 끝내고
그게 아니라면
Pop을 해서 들고 있는 (Action () => 람다로 넘겨준 일감을)
실행 == action.Invoke를 해주면될 것이다.
그런데 지금 이상한 점이
분명히 Flush는 나혼자하는데
Pop을 할때 왜 lock을 잡는지 이상할 텐데
내가 여기서
이렇게 하나하나씩 꺼내는 와중에도
다른애가
여기다가 일감을 밀어 넣을 수 있다.
그래서 Pop을 할대도 lock을 잡고 해야
A라는 쓰레드가 Push에서 락을 잡는다.(다른애가 Push를 못하는 상황)
그리고 _jobQueue에다가 일감을 밀어 넣는다.
lock 안에서 flush가 true로 바뀌어서 Flush함수로 간다.
(그러면 A가 잡고있던 lock은 풀린다? == 다른 B라는 쓰레드가 들어 올 수도 있다 -> 맞나요?? 아니면 A라는 쓰레드가 Flush함수를 호출을 하더라도 계속 lock을 잡고있는것인가요? 아니면 Flush를 실행하러 lock을 풀고 가는것인가요?? )
(A는 Flush함수를 실행하러 왓기에 Push의 lock은 풀려있는 상태이다?)
지금까지 코드가 잘못됨
지금 이부분이 lock밖에서 실행되는 애임
그리고 답변글
그래서 나중에 _jobQueue의 일감이 다 끝났다면
이렇게 false로 풀어주어서
다른애가 Flush하고 Pop을 관리하도록 해준다.
그래서 결국 Push에 여러명이 접근을 해서 일감을 밀어넣는것은 락으로 안전하게 넣고있고
Pop을 하는것은 flush덕분에 한명만 일을 처리하게 되어서
한명만 주방에서 일하는 것이다.
그래서 한번에 한명만 Flush를 실행할 수 있어서
GameRoom >
이런식으로 lock을 잡아서 실행했던부분 없어도 된다.
( 다 지우기 ㄱㄱ)
이런식으로 ㄱㄱ
이렇게되면 Enter, Leave, BroadCast이런 일감들이
요안에 쌓이게 되고
경우에따라 Push로 맨처음 일감을 밀어 넣은애가
실행까지 담당을 하는
구조이다.
그래서 테스트 ㄱㄱ
그래서 보면은
서버랑 클라랑 열심히 열심히 잘 돌아간다.
그래서
쓰레드들도 확연히 줄어든것까지 확인 OK
그런데
C_chatHandler > breakPoint잡고
더미 클라쪽 콘솔창을 끄면은
크래쉬가 난다.
지금 Room이 null로 크래쉬가남
요렇게
그래서 이게 왜 이런 사태가 발생하는지 고민을 해보도록 하자.
우리가 이렇게 람다로 clientSession.Room에 접근을 해서 브로드 캐스트를 하는데
지금 커맨트 패턴으로 실행시점이 뒤로 밀린 것이다.
그래서 이것을 예약을 한 상태에서
Room이 null로 바뀌어서 제거가되면은
결국 clientSession.Room부분에서 Room을 찾지를 못해가지고
크래쉬가 난다.
그래서 ClientSession에서 어디서 Room을 null로 밀어넣고 있는지 보면은
이부분이 문제가 되는 것이였다.
그래서 이것을
이렇게 해주면
Room은 날라가더라도 room은 존재를 하게되니까
"참조"는 유지하고 있으니까ㅣ
room을 이용해서 Leave를 해주면
크래쉬 해결된다.
그래서 PacketHandler에서도 비슷하게 수정을 해주면되는데
Room은 계속 바뀔 수 있으니까
room으로 추출을 한다음에
이렇게 해주고
다시 테스트를 해보면
더미 클라 꺼보면
크래쉬 안나고 잘 된다.