Based on the handle resource management scheme, the first time is to think of windows, but really want me to implement this program, is "game programming essence 1" in the game resources Management chapter of the program. In the Game Programming Essentials 1, the resource label handle class, is a very simple 32-bit int type, the first 16 bits of the index and the last 16-bit magic num,magic num is mainly used as a checksum of the resource, when the instance resources are obtained and the instance resources are deleted, will be verified once. These two data synthesize a int32 used to mark the only resource.
Union {enum{Max_bits_index= -, Max_bits_magic= -, Max_index= (1<< Max_bits_index)-1, Max_magic= (1<< max_bits_magic)-1, }; struct{unsigned mindex:max_bits_index; unsigned mmagic:max_bits_magic; }; UINTMhandle; };
Of course, this handle in the book is defined as a template, the main or to C + + habits, become a strong type of marking it, different resource types can not be assigned to each other and conversion.
Next is the definition of Handlemanager, this class is also a template, like the name, is used to manage the handle, there are two vectors, one is to save the resources in use of the vector, one is to delete the resources to put in the free vector, When a user needs to create a new handle, it takes precedence to find the empty handle from the free vector and re-point to the new resource.
But the index of this handle pointer to the resource instance array will not change, it will change only magic Num. Overall, the handle has changed.
Template<typename DATA, TypeName reshandle>DATA* Reshandlemgr<data, Reshandle>::acquire (Reshandle &handle) { UINTindex; if(Mfreeslots.empty ()) {index=mmagicnums.size (); Handle.init (index); DATA*pdata =NewDATA (); Muservec.push_back (PData); Mmagicnums.push_back (Handle.getmagic ()); } Else{Index=Mfreeslots.back ();
After init, magic Num will add a handle.init (index); Mfreeslots.pop_back (); Mmagicnums[index]=handle.getmagic (); } //return (Muservec.begin () + index);Uservec::iterator iter = Muservec.begin () +index; return*iter;}
This is basically "game programming essence 1" inside the engine resource management solution, to save resources is very simple, hold handle on the line, to get and delete resources directly with handle on the line. However, it is estimated that there is a problem with the resource does not automatically release the mechanism!!!!!!!
So, I added a variable in the handle class to use as a reference count, and there is no smart pointer introduced here (this method of reference counting optimization should be able to add a memory pool)
Private: Union {enum{Max_bits_index= -, Max_bits_magic= -, Max_index= (1<< Max_bits_index)-1, Max_magic= (1<< max_bits_magic)-1, }; struct{unsigned mindex:max_bits_index; unsigned mmagic:max_bits_magic; }; UINTMhandle; }; //Save Reference count UINT*mprefcount;
When the handle is released, Handle.release (), when the handle assignment, Handle.addref, when (*mprefcount) = = 0, you can release resources.
At the beginning, the reference count is set to static Std::map<int, int> (the previous int represents handle, followed by a reference count), and later found that the efficiency is too low, so instead of a UINT *mprefcount pointer this form, The number of frames has risen by about fps ...
This kind of handle class, basically also can realize the automatic release mechanism of resources
Template<typename restype>classEngine_dll reshandle{ Public: Reshandle (); Reshandle (ConstReshandle &handle); ~Reshandle (); voidInitUINTindex); UINTGetIndex ()Const; UINTGetmagic ()Const; UINTGetHandle ()Const; BOOLIsNull ()Const; operator UINT()Const; voidAddRef (); voidrelease (); Reshandle&operator=(Reshandle handle) {Mhandle=Handle.gethandle (); if(Handle.isnull () = =false) {assert (Handle.mprefcount!=0); if(IsNull () = =false&&Mprefcount) {release (); if(Mprefcount! =0) assert (Mprefcount==handle.mprefcount); }} Mprefcount=Handle.mprefcount; AddRef (); return* This; }Private: Union {enum{Max_bits_index= -, Max_bits_magic= -, Max_index= (1<< Max_bits_index)-1, Max_magic= (1<< max_bits_magic)-1, }; struct{unsigned mindex:max_bits_index; unsigned mmagic:max_bits_magic; }; UINTMhandle; }; UINT*Mprefcount;}; Template<typename restype>Reshandle<restype>::reshandle (ConstReshandle &handle): Mprefcount (0) {Mhandle=Handle.gethandle (); Mprefcount=Handle.mprefcount; AddRef ();} Template<typename restype>Reshandle<restype>::~Reshandle () {release ();} Template<typename restype>voidReshandle<restype>:: Release () {if(Mhandle! =0) { --(*mprefcount); if(*mprefcount = =0) { //std::cout << "need delete!!!!" << Std::endl; //Delete operator//Add laterLog::getinstanceptr ()->logmsg ("Release Res handle =%d", Mhandle); Safe_delete (Mprefcount); }}}template<typename restype>voidReshandle<restype>:: AddRef () {if(Mhandle! =0) { ++(*mprefcount); }}template<typename restype>Reshandle<ResType>:: Reshandle (): Mhandle (0), Mprefcount (0) {}template<typename restype>voidReshandle<restype>::init (UINTindex) {Assert (IsNull ()); ASSERT (Index<=Max_index); Static UINTSautomagic =0; if(++sautomagic >max_magic) {Sautomagic=1; } Mindex=index; Mmagic=sautomagic; if(Mprefcount = =0) {Mprefcount=New UINT; } *mprefcount =1;} Template<typename restype>Reshandle<restype>::operator UINT()Const{ returnMhandle;} Template<typename restype>BOOLReshandle<restype>::isnull ()Const{ return!Mhandle;} Template<typename restype>UINTReshandle<restype>::gethandle ()Const{ returnMhandle;} Template<typename restype>UINTReshandle<restype>::getmagic ()Const{ returnMmagic;} Template<typename restype>UINTReshandle<restype>::getindex ()Const{ returnMindex;}//-------------------------------------------------------------------Template< TypeName Tag>inlineBOOL operator! = (reshandle<tag> l, reshandle<tag>R) { return(L.gethandle ()! =R.gethandle ());} Template< TypeName Tag>inlineBOOL operator= = (reshandle<tag> l, reshandle<tag>R) { return(L.gethandle () = =R.gethandle ());}
Game engine based on handle resource management