• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

Session #2 강의 _pending 변수 질문입니다.

21.02.13 18:29 작성 조회수 124

0

안녕하세요! 정말 이만한 게임서버에 관한 강의가 없는데 감사히 수강하고있습니다!

Session #2 강의 보다가 질문을 올립니다.

아직 Session #2까지밖에 안봐서 인지는 모르지만 _pending으로 분기처리를 하는 부분이 왜 필요한지 모르겠습니다.

이미 _lock으로 들어왔으면 다른스레드는 못들어올 텐데 _pending으로 한번 더 분기해서 큐에만 넣고 빠져나올지 아니면 `RegisterSend`까지 해줄지를 결정하는 부분입니다.

_lock에 들어오고 다른 쓰레드가 _pending으로 분기할 경우가 있을지 제 눈에는 도저히 판별하기가 힘드네요 ㅠㅠ 그런 경우가 생기나요?? 우선 _pending의 추가적인 분기없이 실행해도 정상작동합니다!

감사합니다!

답변 4

·

답변을 작성해보세요.

2

네 그 부분을 여쭤보신 것으로 이해했고,
위에 대답은 _pending 에 대한 부분이 맞으니 다시 참고 바랍니다.

RegisterSend 내부에서 호출하는 SendAsync가 '정말' 완료되기 전에는
다른 쓰레드가 중복해서 RegisterSend를 호출하기 원하지 않는 상황입니다.

1

_pending Flag가 추가된 이유는 SendAsync 특성 때문인데요.
비동기 함수 특성상, 호출되자 마자 바로 완료되지 않고
한참 후에 완료될 수도 있습니다. (상대 클라가 모종의 이유로 Recv를 지연해서 받았다거나..)
코드에서 보면 bool pending = _socket.SendAsync()에서 pending이 true로 뜰 때가 지연 처리된 것입니다.

만약에 lock만 걸어서 처리를 하면,
SendAsync 자체는 여러 쓰레드가 동시 접근이 안되는 것은 맞지만
SendAsync가 완료되지 않은 상태에서
_sendArgs를 다른 값으로 바꾸고,
또 다시 SendAsync를 호출하게 되는 문제가 생깁니다.

SendAsync를 여러번 호출하는거 자체는 문제가 아니지만
_sendArgs는 이전 호출이 완료될때까지는 유지를 해줘야 하기 때문에
이를 중간에 수정하면 문제가 됩니다.

따라서 강의 코드에서는 _pending 플래그를 두고
실제 SendAsync가 완료 처리 되었는지를 따로 추적하고 있는 것입니다.
이미 누군가가 SendAsync를 걸어놓은 상태인데
아직 완료 처리가 되지 않은 상태라면
그 쓰레드가 마저 담당해서 처리를 하도록 맡기고 그냥 빠져나오는 것이죠.

0

원아담님의 프로필

원아담

질문자

2021.02.13

           lock(_lock)

            {

                _sendQueue.Enqueue(sendBuff);

                RegisterSend();

            }

이렇게 하면 문제가 발생하나요??

이미 락으로 걸고 들어가서 Send를 처리중에 다른 스레드가 큐에 넣으러 못들어가는거 같아서요!

0

원아담님의 프로필

원아담

질문자

2021.02.13

아, bool pending = _socket.SendAsync() 이 부분말고

Class의 멤버변수 bool _pending 말씀드린거에요!

            lock(_lock)

            {

                _sendQueue.Enqueue(sendBuff);

                

                if (_pending == false)

                {

                    RegisterSend();

                }

            }

이 부분이요!