Torque3D/Engine/source/console/engineObject.cpp

377 lines
12 KiB
C++
Raw Normal View History

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