engineObject.cpp
Engine/source/console/engineObject.cpp
Public Functions
void *&
_USERDATA(EngineObject * object)
DefineNewEngineMethod(EngineObject , addRef , void , () , "Increase the reference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param object An object." )
DefineNewEngineMethod(EngineObject , getType , const EngineTypeInfo * , () , "Return the type descriptor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the type the object is an instance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The type descriptor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the object's dynamic type." )
DefineNewEngineMethod(EngineObject , getUserData , void * , () , "Get the opaque user data <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> installed on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The user data <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> previously installed on the object; <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> by default." )
DefineNewEngineMethod(EngineObject , release , void , () , "Decrease the reference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> of the given object. If the <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> drops <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " " zero, the object will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n\n</a>" " @param object An object." )
DefineNewEngineMethod(EngineObject , setUserData , void , (void *ptr) , "Install an opaque <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> on the object that the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> layer can use <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "associate data with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param ptr A <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pointer.\n</a>" )
IMPLEMENT_NONINSTANTIABLE_CLASS(EngineObject , "Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all objects exposed through the engine API." )
IMPLEMENT_NONINSTANTIABLE_CLASS(StaticEngineObject , "Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> objects that are statically allocated in the engine." )
Detailed Description
Public Functions
_USERDATA(EngineObject * object)
DefineNewEngineMethod(EngineObject , addRef , void , () , "Increase the reference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param object An object." )
DefineNewEngineMethod(EngineObject , getType , const EngineTypeInfo * , () , "Return the type descriptor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the type the object is an instance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The type descriptor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the object's dynamic type." )
DefineNewEngineMethod(EngineObject , getUserData , void * , () , "Get the opaque user data <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> installed on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The user data <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> previously installed on the object; <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> by default." )
DefineNewEngineMethod(EngineObject , release , void , () , "Decrease the reference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> of the given object. If the <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1ad43c3812e6d13e0518d9f8b8f463ffcf">count</a> drops <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " " zero, the object will be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n\n</a>" " @param object An object." )
DefineNewEngineMethod(EngineObject , setUserData , void , (void *ptr) , "Install an opaque <a href="/coding/file/pointer_8h/#pointer_8h_1aae1f8d263916ad71bd415381591549c0">pointer</a> on the object that the <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> layer can use <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "associate data with the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param ptr A <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pointer.\n</a>" )
IMPLEMENT_NONINSTANTIABLE_CLASS(EngineObject , "Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all objects exposed through the engine API." )
IMPLEMENT_NONINSTANTIABLE_CLASS(StaticEngineObject , "Abstract base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> objects that are statically allocated in the engine." )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "console/engineObject.h" 25#include "console/engineAPI.h" 26#include "platform/tmm_off.h" 27 28 29IMPLEMENT_NONINSTANTIABLE_CLASS( EngineObject, 30 "Abstract base class for all objects exposed through the engine API." ) 31END_IMPLEMENT_CLASS; 32IMPLEMENT_NONINSTANTIABLE_CLASS( StaticEngineObject, 33 "Abstract base class <a href="/coding/file/types_8visualc_8h/#types_8visualc_8h_1aad3a54ef5fb260160ec7493483246022">for</a> objects that are statically allocated in the engine." ) 34END_IMPLEMENT_CLASS; 35 36 37#ifdef TORQUE_DEBUG 38U32 EngineObject::smNumEngineObjects; 39EngineObject* EngineObject::smFirstEngineObject; 40#endif 41 42 43IEngineObjectPool* IEngineObjectPool::DEFAULT = EngineCRuntimeObjectPool::instance(); 44EngineCRuntimeObjectPool EngineCRuntimeObjectPool::smInstance; 45 46// Helper to get to engine object's user data. Not exposed through get/set methods 47// as the rest of the engine has no business accessing this data. It is for the 48// exclusive use by the control layer. 49void*& _USERDATA( EngineObject* object ) 50{ 51 return object->mEngineObjectUserData; 52} 53 54//----------------------------------------------------------------------------- 55 56EngineObject::EngineObject() 57 : mEngineObjectPool(NULL), mEngineObjectUserData( NULL ) 58{ 59 #ifdef TORQUE_DEBUG 60 // Add to instance list. 61 62 mNextEngineObject = smFirstEngineObject; 63 mPrevEngineObject = NULL; 64 65 if( smFirstEngineObject ) 66 smFirstEngineObject->mPrevEngineObject = this; 67 smFirstEngineObject = this; 68 69 smNumEngineObjects ++; 70 #endif 71} 72 73//----------------------------------------------------------------------------- 74 75EngineObject::~EngineObject() 76{ 77 #ifdef TORQUE_DEBUG 78 if( mPrevEngineObject ) 79 mPrevEngineObject->mNextEngineObject = mNextEngineObject; 80 else 81 smFirstEngineObject = mNextEngineObject; 82 83 if( mNextEngineObject ) 84 mNextEngineObject->mPrevEngineObject = mPrevEngineObject; 85 86 smNumEngineObjects --; 87 #endif 88} 89 90//----------------------------------------------------------------------------- 91 92void EngineObject::destroySelf() 93{ 94 if( !engineAPI::gUseConsoleInterop ) 95 AssertFatal( !getRefCount() || TYPEOF( this )->isDisposable(), "EngineObject::destroySelf - object still referenced!" ); 96 97 // Call the internal _destroySelf(). 98 99 _destroySelf(); 100 101 // Destruct the object and release it in the pool. 102 103 IEngineObjectPool* pool = this->mEngineObjectPool; 104 void* object = this; 105 106 destructInPlace( this ); 107 if( pool ) 108 pool->freeObject( object ); 109} 110 111//----------------------------------------------------------------------------- 112 113String EngineObject::describeSelf() const 114{ 115 String desc = String::ToString( "class: %s", TYPEOF( this )->getFullyQualifiedExportName().c_str() ); 116 117 return desc; 118} 119 120//----------------------------------------------------------------------------- 121 122#ifndef TORQUE_DISABLE_MEMORY_MANAGER 123void* EngineObject::operator new( size_t size ) 124{ 125 AssertFatal( IEngineObjectPool::DEFAULT, "EngineObject::new - No default pool set!" ); 126 127 void* ptr = IEngineObjectPool::DEFAULT->allocateObject( size TORQUE_TMM_LOC ); 128 if( !ptr ) 129 { 130 Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n"); 131 Platform::forceShutdown( -1 ); 132 } 133 134 EngineObject* object = reinterpret_cast< EngineObject* >( ptr ); 135 object->mEngineObjectPool = IEngineObjectPool::DEFAULT; 136 137 return ptr; 138} 139#endif 140 141//----------------------------------------------------------------------------- 142 143#ifndef TORQUE_DISABLE_MEMORY_MANAGER 144void* EngineObject::operator new( size_t size, IEngineObjectPool* pool ) 145{ 146 AssertFatal( pool, "EngineObject::new - Got a NULL pool pointer!" ); 147 148 void* ptr = pool->allocateObject( size TORQUE_TMM_LOC ); 149 if( !ptr ) 150 { 151 // Fall back to default pool. 152 153 pool = IEngineObjectPool::DEFAULT; 154 AssertFatal( pool, "EngineObject::new - No default pool set!" ); 155 ptr = pool->allocateObject( size TORQUE_TMM_LOC ); 156 157 if( !ptr ) 158 { 159 Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n"); 160 Platform::forceShutdown( -1 ); 161 } 162 } 163 164 EngineObject* object = reinterpret_cast< EngineObject* >( ptr ); 165 object->mEngineObjectPool = pool; 166 167 return ptr; 168} 169#endif 170 171//----------------------------------------------------------------------------- 172 173void* EngineObject::operator new( size_t size TORQUE_TMM_ARGS_DECL ) 174{ 175 AssertFatal( IEngineObjectPool::DEFAULT, "EngineObject::new - No default pool set!" ); 176 177 void* ptr = IEngineObjectPool::DEFAULT->allocateObject( size TORQUE_TMM_ARGS ); 178 if( !ptr ) 179 { 180 Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n"); 181 Platform::forceShutdown( -1 ); 182 } 183 184 EngineObject* object = reinterpret_cast< EngineObject* >( ptr ); 185 object->mEngineObjectPool = IEngineObjectPool::DEFAULT; 186 187 return ptr; 188} 189 190//----------------------------------------------------------------------------- 191 192void* EngineObject::operator new( size_t size, IEngineObjectPool* pool TORQUE_TMM_ARGS_DECL ) 193{ 194 AssertFatal( pool, "EngineObject::new - Got a NULL pool pointer!" ); 195 196 void* ptr = pool->allocateObject( size TORQUE_TMM_ARGS ); 197 if( !ptr ) 198 { 199 // Fall back to default pool. 200 201 pool = IEngineObjectPool::DEFAULT; 202 AssertFatal( pool, "EngineObject::new - No default pool set!" ); 203 ptr = pool->allocateObject( size TORQUE_TMM_ARGS ); 204 205 if( !ptr ) 206 { 207 Platform::AlertOK( "Torque Memory Error", "Out of memory. Shutting down.\n"); 208 Platform::forceShutdown( -1 ); 209 } 210 } 211 212 EngineObject* object = reinterpret_cast< EngineObject* >( ptr ); 213 object->mEngineObjectPool = pool; 214 215 return ptr; 216} 217 218//----------------------------------------------------------------------------- 219 220void EngineObject::operator delete( void* ptr ) 221{ 222 if( !ptr ) 223 return; 224 225// AssertWarn( false, "EngineObject::delete - Directly deleting an EngineObject is disallowed!" ); 226 227 EngineObject* object = reinterpret_cast< EngineObject* >( ptr ); 228 AssertFatal( !object->getRefCount(), "EngineObject::delete - object still referenced!" ); 229 if( object->mEngineObjectPool ) 230 object->mEngineObjectPool->freeObject( object ); 231} 232 233//----------------------------------------------------------------------------- 234 235#ifdef TORQUE_DEBUG 236 237void EngineObject::debugDumpInstances() 238{ 239 Con::printf( "----------- Dumping EngineObjects ----------------" ); 240 for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject ) 241 Con::printf( object->describeSelf() ); 242 Con::printf( "%i EngineObjects", smNumEngineObjects ); 243} 244 245//----------------------------------------------------------------------------- 246 247void EngineObject::debugEnumInstances( const std::type_info& type, DebugEnumInstancesCallback callback ) 248{ 249 for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject ) 250 if( typeid( *object ) == type ) 251 { 252 // Set breakpoint here to break for each instance. 253 if( callback ) 254 callback( object ); 255 } 256} 257 258//----------------------------------------------------------------------------- 259 260void EngineObject::debugEnumInstances( const char* className, DebugEnumInstancesCallback callback ) 261{ 262 for( EngineObject* object = smFirstEngineObject; object != NULL; object = object->mNextEngineObject ) 263 { 264 for( const EngineTypeInfo* type = TYPEOF( object ); type != NULL; type = type->getSuperType() ) 265 if( dStricmp( type->getTypeName(), className ) == 0 ) 266 { 267 // Set breakpoint here to break for each instance. 268 if( callback ) 269 callback( object ); 270 271 break; 272 } 273 } 274} 275 276#endif // TORQUE_DEBUG 277 278//----------------------------------------------------------------------------- 279 280void* EngineCRuntimeObjectPool::allocateObject( U32 size TORQUE_TMM_ARGS_DECL ) 281{ 282 #ifdef TORQUE_DISABLE_MEMORY_MANAGER 283 return dMalloc( size ); 284 #else 285 return dMalloc_r( size TORQUE_TMM_ARGS ); 286 #endif 287} 288 289//----------------------------------------------------------------------------- 290 291void EngineCRuntimeObjectPool::freeObject( void* ptr ) 292{ 293 dFree( ptr ); 294} 295 296//----------------------------------------------------------------------------- 297 298StaticEngineObject::StaticEngineObject() 299{ 300 mEngineObjectPool = NULL; 301 302 // Add an artificial reference to the object. 303 incRefCount(); 304} 305 306//----------------------------------------------------------------------------- 307 308void StaticEngineObject::destroySelf() 309{ 310 AssertFatal( false, "StaticEngineObject::destroySelf - Cannot destroy static object!" ); 311} 312 313//============================================================================= 314// API. 315//============================================================================= 316// MARK: ---- API ---- 317 318//----------------------------------------------------------------------------- 319 320DefineNewEngineMethod( EngineObject, getType, const EngineTypeInfo*, (),, 321 "Return the type descriptor for the type the object is an instance of.\n" 322 "@return The type descriptor for the object's dynamic type." ) 323{ 324 return TYPEOF( object ); 325} 326 327//----------------------------------------------------------------------------- 328 329DefineNewEngineMethod( EngineObject, addRef, void, (),, 330 "Increase the reference count of the given object.\n\n" 331 "@param object An object." ) 332{ 333 object->incRefCount(); 334} 335 336//----------------------------------------------------------------------------- 337 338DefineNewEngineMethod( EngineObject, release, void, (),, 339 "Decrease the reference count of the given object. If the count drops to " 340 "zero, the object will be deleted.\n\n" 341 "@param object An object." ) 342{ 343 object->decRefCount(); 344} 345 346//----------------------------------------------------------------------------- 347 348DefineNewEngineMethod( EngineObject, getUserData, void*, (),, 349 "Get the opaque user data pointer installed on the object.\n" 350 "@return The user data pointer previously installed on the object; NULL by default." ) 351{ 352 return _USERDATA( object ); 353} 354 355//----------------------------------------------------------------------------- 356 357DefineNewEngineMethod( EngineObject, setUserData, void, ( void* ptr ),, 358 "Install an opaque pointer on the object that the control layer can use to " 359 "associate data with the object.\n" 360 "@param ptr A pointer.\n" ) 361{ 362 _USERDATA( object ) = ptr; 363} 364 365//----------------------------------------------------------------------------- 366 367#ifdef TORQUE_DEBUG 368 369DefineEngineFunction( debugDumpAllObjects, void, (),, 370 "@brief Dumps all current EngineObject instances to the console.\n\n" 371 "@note This function is only available in debug builds.\n\n" 372 "@ingroup Debugging" ) 373{ 374 EngineObject::debugDumpInstances(); 375} 376 377#endif // TORQUE_DEBUG 378