인프런 커뮤니티 질문&답변

G General님의 프로필 이미지
G General

작성한 질문수

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

Session #3

sessionFactory 관련 질문드립니다!

작성

·

266

0

SessionRef Service::CreateSession()
{
  SessionRef session = _sessionFactory();
  session->SetService(shared_from_this());

  if (_iocpCore->Register(session) == false)
    return nullptr;

  return session;
}
-----------------------------
using SessionFactory = function<SessionRef(void)>;
-------------------------------
_sessionFactory() F12로 진입
_Ret operator()(_Types... _Argsconst {
  if (_Empty()) {
      _Xbad_function_call();
  }
  const auto _Impl = _Getimpl();
  return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
}
----------------------------------
위의 _Getimpl() F12로 진입
_Storage _Mystorage;
enum { _EEN_IMPL = _Small_object_num_ptrs - 1 }; // helper for expression evaluator
_Ptrt_Getimpl() const noexcept { // get pointer to object
    return _Mystorage._Ptrs[_Small_object_num_ptrs - 1];
}
----------------------------------

강의에서 functional 헤더를 끌고와서 sessionFactory를 사용해주셨는데요! _sessionFactory가 결국 void를 받아서 SessionRef를 리턴해주는 함수인 것은 알겠는데, 메모리 할당이 어떻게 되는건지 모르겠습니다.

애초에 이게 궁금했던 이유가, 

SendBufferChunkRef SendBufferManager::Pop() 에서 return값으로 주는 SendBufferChunkRef(xnew<SendBufferChunk>(), PushGlobal)과 형태가 달라서였기 때문인데요

chunkref의 경우 xnew로 생성하기 때문에 우리가 설정한 PoolAllocator 정책에 따라 메모리풀에서 가져다 쓸텐데, 위의 SessionRef session의 경우에 우리가 xnew로 호출한 것이 아니라 _sessionFactory()의 리턴값을 넣어주게되는데, 이게 세션팩토리가 메모리를 어떻게 할당하겠다고는 전혀 선언한 바가 없기 때문에 new SessionRef를 하는지 xnew<SessionRef>를 하는지를 모르겠습니다. 아마 그냥 new SessionRef를 할 것 같다고 추측만 하고 있습니다.

어찌어찌 이를 좀 더 알아보기 위해서 GetImpl까지 들어왔고 _MyStorage._Ptrs 를 호출하는것까지는 봤는데 여기서 더 이상 진행이 안 되네요ㅠ 짧은생각에 추측하기로 그냥 new로 때릴 것 같깉한데 _MyStorage._Ptr 에서 끝나버려서 잘 모르겠습니다..!

사실 그냥 new여도 크게 상관은 없어보이는데 복습하다가 잘 이해가 안 가서 질문드렸습니다! 인터넷으로 검색도 해보긴했는데, 제가 뭘 모르는지 모르는 초보 수준이라 c++ function default allocator, std::function return value  이런식으로 찾아봤는데 잘 못 찾겠더라구요ㅠ

답변 1

1

Rookiss님의 프로필 이미지
Rookiss
지식공유자

_sessionFactory가 결국 void를 받아서 SessionRef를 리턴해주는 함수인 것은 알겠는데

_sessionFactory가 void를 받아서 SessionRef를 리턴해주는 함수인 것은 아니고,
정확히는 그런 함수를 저장할 수 있는 변수에 불과합니다.
즉 일종의 함수 포인터라고 생각하면 됩니다.
_sessionFactory에다가 어떤 함수를 지정해줘야 하는데,
그 부분은 Service 쪽에서 해주고 있고

실제 컨텐츠 코드에서 함수를 지정해주는 겁니다.

MakeShared<GameSession>을 세션 생성 함수로 지정했으니
_sessionFactory가 호출되면, MakeShared<GameSession>가 실행되는 것이죠.

그런데 왜 굳이 함수 포인터를 사용했을까요?
즉 ServerCore에서 MakeShared<Session>을 하지 않은 이유가 있을까요?
~에 대해서 잘 생각해보실 필요가 있습니다.
Session은 아직 미완성인 class이고 나중에 컨텐츠 단에서는
GameSession처럼 Session을 상속 받아서 기능을 추가할 필요가 생기는데,
MakeShared<Session>으로 ServerCore에서 바로 만들어 버리면
이를 확장성 있게 사용할 수 없기에
Session 생성하는 함수 자체를 컨텐츠 코드에서 지정하는 것이죠.

G General님의 프로필 이미지
G General
질문자

팩토리는 결국 기본 클래스인 Session이 아니라 확장클래스인 GameSession ClientSession 등등의 shared_ptr을 뱉어내야하기 때문에 함수포인터로 넘겨주고 서비스에서 세션을 생성할 때 _sessionFactory()를 호출해서 전달받은 함수포인터 실행 >> MakeShared<GameSession>() 실행.

서비스에서 factory 지정해주는 것까지 분명히 흐름은 알고 있었는데

따로 떼놓고 _sessionFactory() 코드를 보는 순간 컨텐츠단에서 serviceref 생성자에서 매개변수로 밀어넣어준 과정들은 다 까먹어버리고 바로 무지성이 되버리네요ㅠㅜ 감사합니당!

G General님의 프로필 이미지
G General

작성한 질문수

질문하기