1
0
forked from 0ad/0ad

ConfigDB.cpp: fix vfs_load return value check

baseentity, entity: remove multiple property adds (source of
scriptablecomplex memory leak)
scriptablecomplex: add code to check for leak regression and prevent
them; add suballocator for properties, since 60k are allocated in a
short while (!) - saves time and memory

This was SVN commit r3429.
This commit is contained in:
janwas 2006-01-28 22:21:54 +00:00
parent e07622b56a
commit 0fa0bfcb28
5 changed files with 96 additions and 16 deletions

View File

@ -246,20 +246,20 @@ bool CConfigDB::Reload(EConfigNamespace ns)
FileIOBuf buffer;
uint buflen;
File f;
Handle fh;
LibError ret;
if (m_UseVFS[ns])
{
// Open file with VFS
fh=vfs_load(m_ConfigFile[ns], buffer, buflen);
if (fh <= 0)
ret = vfs_load(m_ConfigFile[ns], buffer, buflen);
if(ret != ERR_OK)
{
LOG(ERROR, LOG_CATEGORY, "vfs_load for \"%s\" failed: return was %lld", m_ConfigFile[ns].c_str(), fh);
LOG(ERROR, LOG_CATEGORY, "vfs_load for \"%s\" failed: return was %lld", m_ConfigFile[ns].c_str(), ret);
return false;
}
}
else
{
if (file_open(m_ConfigFile[ns], 0, &f)!=0)
if (file_open(m_ConfigFile[ns], 0, &f)!=ERR_OK)
{
LOG(ERROR, LOG_CATEGORY, "file_open for \"%s\" failed", m_ConfigFile[ns].c_str());
return false;

View File

@ -0,0 +1,38 @@
#include "precompiled.h"
#include "ScriptableComplex.h"
// suballocator for CJSComplex.m_Properties elements
static Bucket bucket;
// HACK: it needs to be created/destroyed; since there is no
// global init/shutdown call here, we keep a refcnt. this assumes that
// going to 0 <==> shutdown! if that proves wrong, bucket_alloc will warn.
static uint suballoc_refs; // initialized in suballoc_attach
void jscomplexproperty_suballoc_attach()
{
ONCE(\
size_t el_size = MAX(sizeof(CJSValComplexProperty), sizeof(CJSComplexProperty<int, true>));\
(void)bucket_create(&bucket, el_size);\
suballoc_refs = 0;\
);
suballoc_refs++;
}
void jscomplexproperty_suballoc_detach()
{
suballoc_refs--;
if(suballoc_refs == 0)
bucket_destroy(&bucket);
}
void* jscomplexproperty_suballoc()
{
return bucket_alloc(&bucket, 0);
}
void jscomplexproperty_suballoc_free(IJSComplexProperty* p)
{
// explicit dtor since caller uses placement new
p->~IJSComplexProperty();
bucket_free(&bucket, p);
}

View File

@ -6,6 +6,8 @@
#include "scripting/ScriptingHost.h"
#include "JSConversions.h"
#include "lib/allocators.h"
#include <set>
#ifndef SCRIPTABLE_COMPLEX_INCLUDED
@ -470,6 +472,13 @@ public:
}
};
extern void jscomplexproperty_suballoc_attach();
extern void jscomplexproperty_suballoc_detach();
extern void* jscomplexproperty_suballoc();
extern void jscomplexproperty_suballoc_free(IJSComplexProperty* p);
template<typename T, bool ReadOnly> class CJSComplex : public IJSComplex
{
typedef STL_HASH_MAP<CStrW, CJSReflector*, CStrW_hash_compare> ReflectorTable;
@ -480,6 +489,7 @@ template<typename T, bool ReadOnly> class CJSComplex : public IJSComplex
ReflectorTable m_Reflectors;
public:
static JSClass JSI_class;
@ -760,6 +770,8 @@ private:
public:
CJSComplex()
{
jscomplexproperty_suballoc_attach();
m_Parent = NULL;
m_JS = NULL;
m_EngineOwned = true;
@ -767,6 +779,8 @@ public:
virtual ~CJSComplex()
{
Shutdown();
jscomplexproperty_suballoc_detach();
}
void Shutdown()
{
@ -785,7 +799,8 @@ public:
JS_RemoveRoot( g_ScriptingHost.GetContext(), &( extProp->m_JSAccessor ) );
}
}
delete( it->second );
jscomplexproperty_suballoc_free(it->second);
}
@ -899,8 +914,11 @@ public:
}
void AddProperty( CStrW PropertyName, jsval Value )
{
debug_assert( !HasProperty( PropertyName ) );
CJSDynamicComplexProperty* newProp = new CJSValComplexProperty( Value, false );
DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "nommgr.h"
CJSDynamicComplexProperty* newProp = new(mem) CJSValComplexProperty( Value, false );
#include "mmgr.h"
m_Properties[PropertyName] = newProp;
ReflectorTable::iterator it;
@ -938,13 +956,43 @@ public:
{
T::m_IntrinsicProperties[PropertyName] = new CJSSharedProperty<PropType, true>( (PropType IJSComplex::*)Native, PropAllowInheritance, Update, Refresh );
}
// helper routine for Add*Property. Their interface requires the
// property not already exist; we check for this (in non-final builds)
// and if so, warn and free the previously new-ed memory in
// m_Properties[PropertyName] (avoids mem leak).
void DeletePreviouslyAssignedProperty( CStrW PropertyName )
{
#ifndef FINAL
PropertyTable::iterator it;
it = m_Properties.find( PropertyName );
if( it != m_Properties.end() )
{
debug_warn("BUG: CJSComplexProperty added but already existed!");
jscomplexproperty_suballoc_free(it->second);
}
#else
UNUSED2(PropertyName);
#endif
}
// PropertyName must not already exist! (verified in non-final release)
template<typename PropType> void AddProperty( CStrW PropertyName, PropType* Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
{
m_Properties[PropertyName] = new CJSComplexProperty<PropType, ReadOnly>( Native, PropAllowInheritance, Update, Refresh );
DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "nommgr.h"
m_Properties[PropertyName] = new(mem) CJSComplexProperty<PropType, ReadOnly>( Native, PropAllowInheritance, Update, Refresh );
#include "mmgr.h"
}
// PropertyName must not already exist! (verified in non-final release)
template<typename PropType> void AddReadOnlyProperty( CStrW PropertyName, PropType* Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
{
m_Properties[PropertyName] = new CJSComplexProperty<PropType, true>( Native, PropAllowInheritance, Update, Refresh );
DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "nommgr.h"
m_Properties[PropertyName] = new(mem) CJSComplexProperty<PropType, true>( Native, PropAllowInheritance, Update, Refresh );
#include "mmgr.h"
}
};

View File

@ -45,9 +45,6 @@ CBaseEntity::CBaseEntity()
AddProperty( L"traits.anchor.type", &m_anchorType );
AddProperty( L"traits.vision.los", &m_los );
AddProperty( L"traits.vision.permanent", &m_permanent );
AddProperty( L"traits.health.regen_rate", &m_healthRegenRate );
AddProperty( L"traits.health.regen_start", &m_healthRegenStart );
AddProperty( L"traits.health.decay_rate", &m_healthDecayRate );
for( int t = 0; t < EVENT_LAST; t++ )
{

View File

@ -69,9 +69,6 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
AddProperty( L"traits.anchor.type", &m_anchorType );
AddProperty( L"traits.vision.los", &m_los );
AddProperty( L"traits.vision.permanent", &m_permanent );
AddProperty( L"traits.health.regen_rate", &m_healthRegenRate );
AddProperty( L"traits.health.regen_start", &m_healthRegenStart );
AddProperty( L"traits.health.decay_rate", &m_healthDecayRate );
AddProperty( L"last_combat_time", &m_lastCombatTime );
for( int t = 0; t < EVENT_LAST; t++ )