engineObject.cpp 12 KB

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