[gpg 스터디] 1.6 범용 핸들 기반 자원 관리자

15
GPG 1.6 범용 핸들 기반 자원 관리자 P. 115 - 129 NHN NEXT 남현욱

Upload: sehyeon-nam

Post on 26-May-2015

156 views

Category:

Software


0 download

DESCRIPTION

게임에서 사용되는 자원(Resource)들, 잘 관리하고 계신가요? GPG 1권쯤의 프로그래머들은 어떤 방식으로 자원을 관리했는지 한번 알아봅시다. NHN NEXT 남현욱님의 발표입니다.

TRANSCRIPT

Page 1: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

GPG1.6 범용 핸들 기반 자원 관리자

P. 115 - 129

NHN NEXT남현욱

Page 2: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

자원 관리의 필요성

• 자원의중복생성 - 어떤 자원이 이미 생성된 자원이고 하나만 있으면 충분한 경우, 이를 단 하나만 생성하도록 제어해주는 것이 좋다

• 자원의공유관리 - 어떤 한 자원이 여러 개체에 의해 사용될 때 이를 관리하지 않으면 댕글링 포인터 등의 문제가 생긴다.

• 성능과안전성확보 - 자원의 생성과 해제 시점, 상태를 관리함으로써 성능을 유지하면서 시스템의 안전성을 확보 할 수 있다.

Page 3: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

방법핸들(Handle)개념을이용하자

메모리

포인터

핸들

관리자포인터를 핸들이라는 추상화 층으로 한 번 더 감싸서 관리함으로써 제어하기 힘들고 위험한 포인터를 직접적으로 건네주지 않는다.

Page 4: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들(Handle)클래스가장간단한방법은두개의비트필드요소를이용하는것-각각 index, magicNumber의 역할을 한다. index는 Handle과 연결된 자원이 무엇인지를 판별하는 식별자 역할을 하며, magicNumber는 해당 핸들이 유효한지를 검증하는 역할을 한다.

핸들은읽기전용- 핸들은 데이터를 참조하기 위한 값이므로 한 번 생성되면 수정될 일은 거의 없다고 봐도 된다.

구분을위한태그(Tag)의이용-범용적으로 이용되는 클래스기 때문에 서로 다른 자원에 대한 핸들이 서로 타입 구분이 되지 않는다. 따라서 이를 구분하기 위한 용도로 태그를 이용한다(코드 참조)

Page 5: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들(Handle)클래스

template <typename TAG>class Handle{public: Handle() : m_Handle(0) { } void Init(unsigned int index);

unsigned int GetIndex() const; unsigned int GetMagic() const; unsigned int GetHandle() const; bool IsNull () const;

private: union { enum { MAX_BITS_INDEX = 16, MAX_BITS_MAGIC = 16,

MAX_INDEX = (1 << MAX_BITS_INDEX) - 1, MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1, }

struct { unsigned m_Index : MAX_BITS_INDEX; unsigned m_Magic : MAX_BITS_MAGIC; };

unsigned int m_Handle; }};

template <typename TAG>void Handle<TAG> ::Init(unsigned int index){ static unsigned int s_AutoMagic = index;

if (++s_AutoMagic > MAX_MAGIC) { s_AutoMagic = 1; } m_Index = index; m_Magic = s_AutoMagic;}

Page 6: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들(Handle)클래스

template <typename TAG>class Handle{public: Handle() : m_Handle(0) { } void Init(unsigned int index);

unsigned int GetIndex() const; unsigned int GetMagic() const; unsigned int GetHandle() const; bool IsNull () const;

private: union { enum { MAX_BITS_INDEX = 16, MAX_BITS_MAGIC = 16,

MAX_INDEX = (1 << MAX_BITS_INDEX) - 1, MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1, }

struct { unsigned m_Index : MAX_BITS_INDEX; unsigned m_Magic : MAX_BITS_MAGIC; };

unsigned int m_Handle; }};

template <typename TAG>void Handle<TAG> ::Init(unsigned int index){ static unsigned int s_AutoMagic = index;

if (++s_AutoMagic > MAX_MAGIC) { s_AutoMagic = 1; } m_Index = index; m_Magic = s_AutoMagic;}

핸들 구분을 위한 태그. 오로지 구분 만을 위한 목적이므로 빈 구조체같은 걸 이용하는게 좋다.

ex)struct TagTexture{};typedef Handle<TagTexture> HTexture;HTexture hTexture;

Page 7: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들(Handle)클래스

template <typename TAG>class Handle{public: Handle() : m_Handle(0) { } void Init(unsigned int index);

unsigned int GetIndex() const; unsigned int GetMagic() const; unsigned int GetHandle() const; bool IsNull () const;

private: union { enum { MAX_BITS_INDEX = 16, MAX_BITS_MAGIC = 16,

MAX_INDEX = (1 << MAX_BITS_INDEX) - 1, MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1, }

struct { unsigned m_Index : MAX_BITS_INDEX; unsigned m_Magic : MAX_BITS_MAGIC; };

unsigned int m_Handle; }};

template <typename TAG>void Handle<TAG> ::Init(unsigned int index){ static unsigned int s_AutoMagic = index;

if (++s_AutoMagic > MAX_MAGIC) { s_AutoMagic = 1; } m_Index = index; m_Magic = s_AutoMagic;}

내부적으로 핸들은 아래와 같은 구조를 지닌다.

m_Handle

m_Index m_Magic

Page 8: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들(Handle)클래스

template <typename TAG>class Handle{public: Handle() : m_Handle(0) { } void Init(unsigned int index);

unsigned int GetIndex() const; unsigned int GetMagic() const; unsigned int GetHandle() const; bool IsNull () const;

private: union { enum { MAX_BITS_INDEX = 16, MAX_BITS_MAGIC = 16,

MAX_INDEX = (1 << MAX_BITS_INDEX) - 1, MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1, }

struct { unsigned m_Index : MAX_BITS_INDEX; unsigned m_Magic : MAX_BITS_MAGIC; };

unsigned int m_Handle; }};

template <typename TAG>void Handle<TAG> ::Init(unsigned int index){ static unsigned int s_AutoMagic = index;

if (++s_AutoMagic > MAX_MAGIC) { s_AutoMagic = 1; } m_Index = index; m_Magic = s_AutoMagic;}

핸들 클래스는 내부적으로 핸들 값의 저장과 매직 넘버를 관리하는 역할만 담당한다. 실제 핸들을 부여하고 관리하는 작업은 핸들 매니저 클래스에서 담당.

Page 9: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들매니저(HandleMgr)클래스핸들매니저는자기가관리하는자원정보와핸들을관리-자원의 정보는 해당 자원에 대한 간단한 데이터들만을 포함한다. 이 데이터가 어떤 메모리의 할

당이라든지 복잡한 행동을 수행해서는 안된다.

핸들의역참조(dereference)를지원- 핸들 값으로부터 그 값이 유효하면 그 핸들이 가리키는 자원의 정보를 돌려주는 기능(역참조)

을 지원한다.

Page 10: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들매니저(HandleMgr)클래스template<typename DATA, typename HANDLE>class HandleMgr{private: std::vector<DATA> m_UserData; std::vector<unsigned int> m_MagicNumbers; std::vector<unsigned int> m_FreeSlots;public: HandleMgr(){} ~HandleMgr(){}

DATA* Acquire(HANDLE& handle); void Release(HANDLE handle); DATA* Dereference(HANDLE handle);};

Page 11: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들매니저(HandleMgr)클래스template<typename DATA, typename HANDLE>class HandleMgr{private: std::vector<DATA> m_UserData; std::vector<unsigned int> m_MagicNumbers; std::vector<unsigned int> m_FreeSlots;public: HandleMgr(){} ~HandleMgr(){}

DATA* Acquire(HANDLE& handle); void Release(HANDLE handle); DATA* Dereference(HANDLE handle);};

template<typename DATA, typename HANDLE>DATA* HandleMgr <DATA, HANDLE> ::Acquire(HANDLE& handle){ unsigned int index;

if (m_FreeSlots.empty()) { index = m_MagicNumbers.size(); handle.Init(index); m_UserData.push_back(DATA()); m_MagicNumbers.push_back(handle.GetMagic()); } else { index = m_FreeSlots.back(); handle.Init(index); m_FreeSlots.pop_back(); m_MagicNumbers[index] = handle.GetMagic(); }

return (m_UserData.begin() + index);}

Page 12: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들매니저(HandleMgr)클래스template<typename DATA, typename HANDLE>class HandleMgr{private: std::vector<DATA> m_UserData; std::vector<unsigned int> m_MagicNumbers; std::vector<unsigned int> m_FreeSlots;public: HandleMgr(){} ~HandleMgr(){}

DATA* Acquire(HANDLE& handle); void Release(HANDLE handle); DATA* Dereference(HANDLE handle);};

template<typename DATA, typename HANDLE>void HandleMgr <DATA, HANDLE>::Release(HANDLE handle){ unsigned int index = handle.GetIndex();

m_MagicNumbers[index] = 0; m_FreeSlots.push_back(index);}

Page 13: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제범용핸들매니저(HandleMgr)클래스template<typename DATA, typename HANDLE>class HandleMgr{private: std::vector<DATA> m_UserData; std::vector<unsigned int> m_MagicNumbers; std::vector<unsigned int> m_FreeSlots;public: HandleMgr(){} ~HandleMgr(){}

DATA* Acquire(HANDLE& handle); void Release(HANDLE handle); DATA* Dereference(HANDLE handle);};

template<typename DATA, typename HANDLE>DATA* HandleMgr <DATA, HANDLE>::Dereference(HANDLE handle){ if (handle.IsNull())return (0);

unsigned int index = handle.GetIndex();

if ((index >= m_UserData.size()) || (m_MagicNumbers[index] != handle.GetMagic())) { return (0); }

return (m_UserData.begin() + index);}

Page 14: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

구현 예제활용struct TagFile{};typedef Handle<TagFile> HFile;

class FileManager{private: struct FileData { std::string m_Name; int m_Length; }; typedef HandleMgr<FileData, HFile> HFileMgr;

HFileMgr m_Files;public: FileManager(); ~FileManager();

HFile GetFile(const char* name); void DeleteFile(HFile hFile);

const std::string& GetName(HFile hFile) const { return (m_Files.Dereference(hFile)->m_Name); }

int GetLength(HFile hFile) const { return (m_Files.Dereference(hFile)->m_Length); }};

Page 15: [GPG 스터디] 1.6 범용 핸들 기반 자원 관리자

범용 핸들 기반 자원 관리자

‘ GPG를 공부하자’ 페이스북 페이지https://www.facebook.com/gpgstudygogo