2012-09-19 15:15:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to
|
|
|
|
|
// deal in the Software without restriction, including without limitation the
|
|
|
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
// IN THE SOFTWARE.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#include "console/engineObject.h"
|
|
|
|
|
#include "console/engineAPI.h"
|
|
|
|
|
#include "platform/tmm_off.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_NONINSTANTIABLE_CLASS( EngineObject,
|
|
|
|
|
"Abstract base class for all objects exposed through the engine API." )
|
|
|
|
|
END_IMPLEMENT_CLASS;
|
|
|
|
|
IMPLEMENT_NONINSTANTIABLE_CLASS( StaticEngineObject,
|
|
|
|
|
"Abstract base class for objects that are statically allocated in the engine." )
|
|
|
|
|
END_IMPLEMENT_CLASS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
U32 EngineObject::smNumEngineObjects;
|
|
|
|
|
EngineObject* EngineObject::smFirstEngineObject;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IEngineObjectPool* IEngineObjectPool::DEFAULT = EngineCRuntimeObjectPool::instance();
|
|
|
|
|
EngineCRuntimeObjectPool EngineCRuntimeObjectPool::smInstance;
|
|
|
|
|
|
|
|
|
|
// Helper to get to engine object's user data. Not exposed through get/set methods
|
|
|
|
|
// as the rest of the engine has no business accessing this data. It is for the
|
|
|
|
|
// exclusive use by the control layer.
|
|
|
|
|
void*& _USERDATA( EngineObject* object )
|
|
|
|
|
{
|
|
|
|
|
return object->mEngineObjectUserData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
EngineObject::EngineObject()
|
2020-05-11 19:40:31 +00:00
|
|
|
: mEngineObjectPool(NULL), mEngineObjectUserData( NULL )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
// Add to instance list.
|
|
|
|
|
|
|
|
|
|
mNextEngineObject = smFirstEngineObject;
|
|
|
|
|
mPrevEngineObject = NULL;
|
|
|
|
|
|
|
|
|
|
if( smFirstEngineObject )
|
|
|
|
|
smFirstEngineObject->mPrevEngineObject = this;
|
|
|
|
|
smFirstEngineObject = this;
|
|
|
|
|
|
|
|
|
|
smNumEngineObjects ++;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
EngineObject::~EngineObject()
|
|
|
|
|
{
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
if( mPrevEngineObject )
|
|
|
|
|
mPrevEngineObject->mNextEngineObject = mNextEngineObject;
|
|
|
|
|
else
|
|
|
|
|
smFirstEngineObject = mNextEngineObject;
|
|
|
|
|
|
|
|
|
|
if( mNextEngineObject )
|
|
|
|
|
mNextEngineObject->mPrevEngineObject = mPrevEngineObject;
|
|
|
|
|
|
|
|
|
|
smNumEngineObjects --;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void EngineObject::destroySelf()
|
|
|
|
|
{
|
|
|
|
|
if( !engineAPI::gUseConsoleInterop )
|
|
|
|
|
AssertFatal( !getRefCount() || TYPEOF( this )->isDisposable(), "EngineObject::destroySelf - object still referenced!" );
|
|
|
|
|
|
|
|
|
|
// Call the internal _destroySelf().
|
|
|
|
|
|
|
|
|
|
_destroySelf();
|
|
|
|
|
|
|
|
|
|
// Destruct the object and release it in the pool.
|
|
|
|
|
|
|
|
|
|
IEngineObjectPool* pool = this->mEngineObjectPool;
|
|
|
|
|
void* object = this;
|
|
|
|
|
|
|
|
|
|
destructInPlace( this );
|
|
|
|
|
if( pool )
|
|
|
|
|
pool->freeObject( object );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
String EngineObject::describeSelf() const
|
|
|
|
|
{
|
|
|
|
|
String desc = String::ToString( "class: %s", TYPEOF( this )->getFullyQualifiedExportName().c_str() );
|
|
|
|
|
|
|
|
|
|
return desc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifndef TORQUE_DISABLE_MEMORY_MANAGER
|
|
|
|
|
void* EngineObject::operator new( size_t size )
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( IEngineObjectPool::DEFAULT, "EngineObject::new - No default pool set!" );
|
|
|
|
|
|
|
|
|
|
void* ptr = IEngineObjectPool::DEFAULT->allocateObject( size TORQUE_TMM_LOC );
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n");
|
|
|
|
|
Platform::forceShutdown( -1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EngineObject* object = reinterpret_cast< EngineObject* >( ptr );
|
|
|
|
|
object->mEngineObjectPool = IEngineObjectPool::DEFAULT;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifndef TORQUE_DISABLE_MEMORY_MANAGER
|
|
|
|
|
void* EngineObject::operator new( size_t size, IEngineObjectPool* pool )
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( pool, "EngineObject::new - Got a NULL pool pointer!" );
|
|
|
|
|
|
|
|
|
|
void* ptr = pool->allocateObject( size TORQUE_TMM_LOC );
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
// Fall back to default pool.
|
|
|
|
|
|
|
|
|
|
pool = IEngineObjectPool::DEFAULT;
|
|
|
|
|
AssertFatal( pool, "EngineObject::new - No default pool set!" );
|
|
|
|
|
ptr = pool->allocateObject( size TORQUE_TMM_LOC );
|
|
|
|
|
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n");
|
|
|
|
|
Platform::forceShutdown( -1 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EngineObject* object = reinterpret_cast< EngineObject* >( ptr );
|
|
|
|
|
object->mEngineObjectPool = pool;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void* EngineObject::operator new( size_t size TORQUE_TMM_ARGS_DECL )
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( IEngineObjectPool::DEFAULT, "EngineObject::new - No default pool set!" );
|
|
|
|
|
|
|
|
|
|
void* ptr = IEngineObjectPool::DEFAULT->allocateObject( size TORQUE_TMM_ARGS );
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n");
|
|
|
|
|
Platform::forceShutdown( -1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EngineObject* object = reinterpret_cast< EngineObject* >( ptr );
|
|
|
|
|
object->mEngineObjectPool = IEngineObjectPool::DEFAULT;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void* EngineObject::operator new( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL )
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( pool, "EngineObject::new - Got a NULL pool pointer!" );
|
|
|
|
|
|
|
|
|
|
void* ptr = pool->allocateObject( size TORQUE_TMM_ARGS );
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
// Fall back to default pool.
|
|
|
|
|
|
|
|
|
|
pool = IEngineObjectPool::DEFAULT;
|
|
|
|
|
AssertFatal( pool, "EngineObject::new - No default pool set!" );
|
|
|
|
|
ptr = pool->allocateObject( size TORQUE_TMM_ARGS );
|
|
|
|
|
|
|
|
|
|
if( !ptr )
|
|
|
|
|
{
|
|
|
|
|
Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n");
|
|
|
|
|
Platform::forceShutdown( -1 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EngineObject* object = reinterpret_cast< EngineObject* >( ptr );
|
|
|
|
|
object->mEngineObjectPool = pool;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void EngineObject::operator delete( void* ptr )
|
|
|
|
|
{
|
|
|
|
|
if( !ptr )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// AssertWarn( false, "EngineObject::delete - Directly deleting an EngineObject is disallowed!" );
|
|
|
|
|
|
|
|
|
|
EngineObject* object = reinterpret_cast< EngineObject* >( ptr );
|
|
|
|
|
AssertFatal( !object->getRefCount(), "EngineObject::delete - object still referenced!" );
|
|
|
|
|
if( object->mEngineObjectPool )
|
|
|
|
|
object->mEngineObjectPool->freeObject( object );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
|
|
|
|
|
void EngineObject::debugDumpInstances()
|
|
|
|
|
{
|
|
|
|
|
Con::printf( "----------- Dumping EngineObjects ----------------" );
|
|
|
|
|
for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject )
|
|
|
|
|
Con::printf( object->describeSelf() );
|
|
|
|
|
Con::printf( "%i EngineObjects", smNumEngineObjects );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void EngineObject::debugEnumInstances( const std::type_info& type, DebugEnumInstancesCallback callback )
|
|
|
|
|
{
|
|
|
|
|
for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject )
|
|
|
|
|
if( typeid( *object ) == type )
|
|
|
|
|
{
|
|
|
|
|
// Set breakpoint here to break for each instance.
|
|
|
|
|
if( callback )
|
|
|
|
|
callback( object );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void EngineObject::debugEnumInstances( const char* className, DebugEnumInstancesCallback callback )
|
|
|
|
|
{
|
|
|
|
|
for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject )
|
|
|
|
|
{
|
|
|
|
|
for( const EngineTypeInfo* type = TYPEOF( object ); type != NULL; type = type->getSuperType() )
|
|
|
|
|
if( dStricmp( type->getTypeName(), className ) == 0 )
|
|
|
|
|
{
|
|
|
|
|
// Set breakpoint here to break for each instance.
|
|
|
|
|
if( callback )
|
|
|
|
|
callback( object );
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // TORQUE_DEBUG
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2023-04-27 21:10:04 +00:00
|
|
|
void* EngineCRuntimeObjectPool::allocateObject(size_t size TORQUE_TMM_ARGS_DECL )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
#ifdef TORQUE_DISABLE_MEMORY_MANAGER
|
|
|
|
|
return dMalloc( size );
|
|
|
|
|
#else
|
|
|
|
|
return dMalloc_r( size TORQUE_TMM_ARGS );
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void EngineCRuntimeObjectPool::freeObject( void* ptr )
|
|
|
|
|
{
|
|
|
|
|
dFree( ptr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
StaticEngineObject::StaticEngineObject()
|
|
|
|
|
{
|
|
|
|
|
mEngineObjectPool = NULL;
|
|
|
|
|
|
|
|
|
|
// Add an artificial reference to the object.
|
|
|
|
|
incRefCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void StaticEngineObject::destroySelf()
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( false, "StaticEngineObject::destroySelf - Cannot destroy static object!" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// API.
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// MARK: ---- API ----
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DefineNewEngineMethod( EngineObject, getType, const EngineTypeInfo*, (),,
|
|
|
|
|
"Return the type descriptor for the type the object is an instance of.\n"
|
|
|
|
|
"@return The type descriptor for the object's dynamic type." )
|
|
|
|
|
{
|
|
|
|
|
return TYPEOF( object );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DefineNewEngineMethod( EngineObject, addRef, void, (),,
|
|
|
|
|
"Increase the reference count of the given object.\n\n"
|
|
|
|
|
"@param object An object." )
|
|
|
|
|
{
|
|
|
|
|
object->incRefCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DefineNewEngineMethod( EngineObject, release, void, (),,
|
|
|
|
|
"Decrease the reference count of the given object. If the count drops to "
|
|
|
|
|
"zero, the object will be deleted.\n\n"
|
|
|
|
|
"@param object An object." )
|
|
|
|
|
{
|
|
|
|
|
object->decRefCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DefineNewEngineMethod( EngineObject, getUserData, void*, (),,
|
|
|
|
|
"Get the opaque user data pointer installed on the object.\n"
|
|
|
|
|
"@return The user data pointer previously installed on the object; NULL by default." )
|
|
|
|
|
{
|
|
|
|
|
return _USERDATA( object );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DefineNewEngineMethod( EngineObject, setUserData, void, ( void* ptr ),,
|
|
|
|
|
"Install an opaque pointer on the object that the control layer can use to "
|
|
|
|
|
"associate data with the object.\n"
|
|
|
|
|
"@param ptr A pointer.\n" )
|
|
|
|
|
{
|
|
|
|
|
_USERDATA( object ) = ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#ifdef TORQUE_DEBUG
|
|
|
|
|
|
|
|
|
|
DefineEngineFunction( debugDumpAllObjects, void, (),,
|
|
|
|
|
"@brief Dumps all current EngineObject instances to the console.\n\n"
|
|
|
|
|
"@note This function is only available in debug builds.\n\n"
|
|
|
|
|
"@ingroup Debugging" )
|
|
|
|
|
{
|
|
|
|
|
EngineObject::debugDumpInstances();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // TORQUE_DEBUG
|