From 8c4b952e6c583b5db1ded54dc4ddc4e4d0f8f516 Mon Sep 17 00:00:00 2001 From: Wanne Date: Mon, 9 Jul 2012 08:16:37 +0000 Subject: [PATCH] - Convert video object cache to hashmap from linked list. This will protect better against video object leaks and probably still be faster than the linked list. (by tazpn) o new #define: USE_HASHMAP_FOR_VOBJECTS git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5370 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Standard Gaming Platform/vobject.cpp | 98 +++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/Standard Gaming Platform/vobject.cpp b/Standard Gaming Platform/vobject.cpp index fedada09..2bb29a36 100644 --- a/Standard Gaming Platform/vobject.cpp +++ b/Standard Gaming Platform/vobject.cpp @@ -20,6 +20,8 @@ #include "sgp.h" #endif +#include + // ****************************************************************************** // // Video Object SGP Module @@ -64,6 +66,22 @@ HLIST ghVideoObjects = NULL; BOOLEAN gfVideoObjectsInit=FALSE; +#define USE_HASHMAP_FOR_VOBJECTS +#ifdef USE_HASHMAP_FOR_VOBJECTS +typedef struct VOBJECT_NODE +{ + HVOBJECT hVObject; + UINT32 uiIndex; +#ifdef SGP_VIDEO_DEBUGGING + STR8 pName; + STR8 pCode; +#endif +} VOBJECT_NODE, *VOBJECT_NODE_PTR; + +typedef std::hash_map VOBJECT_MAP; +static VOBJECT_MAP gpVObjectMap; + +#else typedef struct VOBJECT_NODE { HVOBJECT hVObject; @@ -79,6 +97,7 @@ typedef struct VOBJECT_NODE VOBJECT_NODE *gpVObjectHead = NULL; VOBJECT_NODE *gpVObjectTail = NULL; +#endif UINT32 guiVObjectIndex = 1; UINT32 guiVObjectSize = 0; UINT32 guiVObjectTotalAdded = 0; @@ -130,10 +149,15 @@ BOOLEAN InitializeVideoObjectManager( ) { //Shouldn't be calling this if the video object manager already exists. //Call shutdown first... +#ifdef USE_HASHMAP_FOR_VOBJECTS + Assert( gpVObjectMap.empty() ); + RegisterDebugTopic(TOPIC_VIDEOOBJECT, "Video Object Manager"); +#else Assert( !gpVObjectHead ); Assert( !gpVObjectTail ); RegisterDebugTopic(TOPIC_VIDEOOBJECT, "Video Object Manager"); gpVObjectHead = gpVObjectTail = NULL; +#endif gfVideoObjectsInit=TRUE; return TRUE ; } @@ -141,6 +165,21 @@ BOOLEAN InitializeVideoObjectManager( ) BOOLEAN ShutdownVideoObjectManager( ) { VOBJECT_NODE *curr; +#ifdef USE_HASHMAP_FOR_VOBJECTS + for(VOBJECT_MAP::iterator itr=gpVObjectMap.begin(); itr != gpVObjectMap.end(); ++itr ) + { + curr = (*itr).second; + DeleteVideoObject( curr->hVObject ); +#ifdef SGP_VIDEO_DEBUGGING + if( curr->pName ) + MemFree( curr->pName ); + if( curr->pCode ) + MemFree( curr->pCode ); +#endif + MemFree( curr ); + } + gpVObjectMap.clear(); +#else while( gpVObjectHead ) { curr = gpVObjectHead; @@ -156,6 +195,7 @@ BOOLEAN ShutdownVideoObjectManager( ) } gpVObjectHead = NULL; gpVObjectTail = NULL; +#endif guiVObjectIndex = 1; guiVObjectSize = 0; guiVObjectTotalAdded = 0; @@ -166,6 +206,9 @@ BOOLEAN ShutdownVideoObjectManager( ) UINT32 CountVideoObjectNodes() { +#ifdef USE_HASHMAP_FOR_VOBJECTS + return gpVObjectMap.size(); +#else VOBJECT_NODE *curr; UINT32 i = 0; curr = gpVObjectHead; @@ -175,6 +218,7 @@ UINT32 CountVideoObjectNodes() curr = curr->next; } return i; +#endif } BOOLEAN AddStandardVideoObject( VOBJECT_DESC *pVObjectDesc, UINT32 *puiIndex ) @@ -198,6 +242,17 @@ BOOLEAN AddStandardVideoObject( VOBJECT_DESC *pVObjectDesc, UINT32 *puiIndex ) // Set transparency to default SetVideoObjectTransparencyColor( hVObject, FROMRGB( 0, 0, 0 ) ); +#ifdef USE_HASHMAP_FOR_VOBJECTS + { + VOBJECT_NODE_PTR curr = (VOBJECT_NODE*)MemAlloc( sizeof( VOBJECT_NODE ) ); + memset(curr, 0, sizeof(VOBJECT_NODE)); + curr->hVObject = hVObject; + curr->uiIndex = guiVObjectIndex++; + *puiIndex = curr->uiIndex; + + gpVObjectMap[curr->uiIndex] = curr; + } +#else // Set into video object list if( gpVObjectHead ) { //Add node after tail @@ -222,6 +277,7 @@ BOOLEAN AddStandardVideoObject( VOBJECT_DESC *pVObjectDesc, UINT32 *puiIndex ) gpVObjectTail->hVObject = hVObject; gpVObjectTail->uiIndex = guiVObjectIndex+=2; *puiIndex = gpVObjectTail->uiIndex; +#endif Assert( guiVObjectIndex < 0xfffffff0 ); //unlikely that we will ever use 2 billion vobjects! //We would have to create about 70 vobjects per second for 1 year straight to achieve this... guiVObjectSize++; @@ -254,14 +310,23 @@ BOOLEAN SetVideoObjectTransparency( UINT32 uiIndex, COLORVAL TransColor ) return( TRUE ); } + BOOLEAN GetVideoObject( HVOBJECT *hVObject, UINT32 uiIndex ) { - VOBJECT_NODE *curr; #ifdef _DEBUG CheckValidVObjectIndex( uiIndex ); #endif +#ifdef USE_HASHMAP_FOR_VOBJECTS + VOBJECT_MAP::iterator itr = gpVObjectMap.find(uiIndex); + if (itr != gpVObjectMap.end()) + { + *hVObject = (*itr).second->hVObject; + return TRUE; + } +#else + VOBJECT_NODE *curr; curr = gpVObjectHead; while( curr ) { @@ -272,6 +337,7 @@ BOOLEAN GetVideoObject( HVOBJECT *hVObject, UINT32 uiIndex ) } curr = curr->next; } +#endif *hVObject = NULL; return FALSE; } @@ -322,6 +388,35 @@ BOOLEAN DeleteVideoObjectFromIndex( UINT32 uiVObject ) CheckValidVObjectIndex( uiVObject ); #endif +#ifdef USE_HASHMAP_FOR_VOBJECTS + VOBJECT_MAP::iterator itr = gpVObjectMap.find(uiVObject); + if (itr != gpVObjectMap.end()) + { + curr = (*itr).second; + + DeleteVideoObject( curr->hVObject ); + + //The node is now detached. Now deallocate it. +#ifdef SGP_VIDEO_DEBUGGING + if( curr->pName ) + MemFree( curr->pName ); + if( curr->pCode ) + MemFree( curr->pCode ); +#endif + MemFree( curr ); + curr = NULL; + guiVObjectSize--; + + gpVObjectMap.erase(itr); +#ifdef JA2TESTVERSION + if( CountVideoObjectNodes() != guiVObjectSize ) + { + guiVObjectSize = guiVObjectSize; + } +#endif + return TRUE; + } +#else curr = gpVObjectHead; while( curr ) { @@ -368,6 +463,7 @@ BOOLEAN DeleteVideoObjectFromIndex( UINT32 uiVObject ) } curr = curr->next; } +#endif return FALSE; }