hkCheckDeterminismUtil.h
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:9k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* 
  2.  * 
  3.  * Confidential Information of Telekinesys Research Limited (t/a Havok). Not for disclosure or distribution without Havok's
  4.  * prior written consent. This software contains code, techniques and know-how which is confidential and proprietary to Havok.
  5.  * Level 2 and Level 3 source code contains trade secrets of Havok. Havok Software (C) Copyright 1999-2009 Telekinesys Research Limited t/a Havok. All Rights Reserved. Use of this software is subject to the terms of an end user license agreement.
  6.  * 
  7.  */
  8. #ifndef HKBASE_HKDEBUGUTIL_CHECK_DETERMINISM_UTIL_H
  9. #define HKBASE_HKDEBUGUTIL_CHECK_DETERMINISM_UTIL_H
  10. // Uncomment the next line if you want to check the engine for determinism
  11. //#define HK_ENABLE_DETERMINISM_CHECKS
  12. #if defined (HK_ENABLE_DETERMINISM_CHECKS)
  13. #include <Common/Base/Thread/Thread/hkThreadLocalData.h>
  14. #include <Common/Base/System/Io/IStream/hkIStream.h>
  15. #include <Common/Base/System/Io/OStream/hkOStream.h>
  16. # define HK_ON_DETERMINISM_CHECKS_ENABLED(code) code
  17. #else
  18. # define HK_ON_DETERMINISM_CHECKS_ENABLED(code)
  19. #endif
  20. extern struct hkCheckDeterminismUtil* g_checkDeterminismUtil;
  21. class hkIstream;
  22. class hkOstream;
  23. class hkCriticalSection;
  24. /// This is a small helper class allowing to check the determinism of
  25. /// a system. Basically it works by running an application twice:
  26. /// First a binary logfile is created and the second time the system
  27. /// checks against this binary logfile.
  28. ///
  29. /// Usage quick start:
  30. ///
  31. /// You activate writing or reading+checking with startWriteMode() or startCheckMode() functions from anywhere in your app.
  32. /// Similarly you call finish() when you're done with writing or reading+checking.
  33. ///
  34. /// Then for every single thread that you're intending to use the utility in, you must call workerThreadStartFrame() before 
  35. /// and workerThreadFinishFrame() after any use of the utility.
  36. ///
  37. /// The workerThreadStartFrame() function takes a parameter isPrimaryWorkerThread. This can be true for only one thread. 
  38. /// That 'marked' thread is allowed to used the utility immediately. This is used when the primary thread performs special
  39. /// operations besides the jobs taken off of the job queue.
  40. ///
  41. /// Other threads must register a job first. The primary thread can also register jobs, when it starts working 
  42. /// in parallel to other threads.
  43. ///
  44. /// Why do we need to register jobs? When multithreading, before the utility is used, you must tell it what that thread 
  45. /// is about to start doing -- you must do that, as the same thread may be given different jobs on each consecutive run. 
  46. /// You do that by calling registerAndStartJob() and finishJob(). Those functions take a job ID which must be unique 
  47. /// across all jobs performed during that one frame.
  48. ///
  49. /// Soo, only now after starting, and before finishing a job. You can use the hkCheckDeterminismUtil::checkMt() function. 
  50. struct hkCheckDeterminismUtil
  51. {
  52. public:
  53. HK_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( HK_MEMORY_CLASS_BASE_CLASS, hkCheckDeterminismUtil );
  54. // <ag.todo.a> documentation here ..
  55. // Frame-unique ID
  56. struct Fuid
  57. {
  58. HK_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( HK_MEMORY_CLASS_BASE_CLASS, hkCheckDeterminismUtil::Fuid );
  59. hkUint32 m_0, m_1, m_2, m_3;
  60. static Fuid& getZeroFuid();
  61. hkBool operator==(const Fuid& f)
  62. {
  63. return m_0 == f.m_0 && m_1 == f.m_1 && m_2 == f.m_2 && m_3 == f.m_3;
  64. }
  65. hkBool operator!=(const Fuid& f)
  66. {
  67. return m_0 != f.m_0 || m_1 != f.m_1 || m_2 != f.m_2 || m_3 != f.m_3;
  68. }
  69. };
  70.  hkCheckDeterminismUtil();
  71. ~hkCheckDeterminismUtil();
  72. static hkCheckDeterminismUtil& getInstance() { HK_ASSERT2(0xad8655d2, g_checkDeterminismUtil, "Instance not created."); return *g_checkDeterminismUtil; }
  73. static void HK_CALL createInstance() { HK_ASSERT2(0xad8655d3, !g_checkDeterminismUtil, "Instance already created."); g_checkDeterminismUtil = new hkCheckDeterminismUtil(); }
  74. static void HK_CALL destroyInstance() { delete g_checkDeterminismUtil; g_checkDeterminismUtil = HK_NULL; }
  75. /// Starts the utility in write or check mode, depending on if the data file exists.
  76. /// Make sure to call finish() at the end.
  77. void start(const char* filename = "hkDeterminismCheckfile.bin");
  78. /// Sets this utility to write mode. Call at startup of your test
  79. /// Make sure to call finish() at the end.
  80. void startWriteMode(const char* filename = "hkDeterminismCheckfile.bin");
  81. /// Sets this utility to check mode. Call at startup of your test
  82. /// Make sure to call finish() at the end.
  83. void startCheckMode(const char* filename = "hkDeterminismCheckfile.bin");
  84. //
  85. // Registration functions used at the beginning and end of each hkpDynamicsJob.
  86. //
  87. # if defined (HK_ENABLE_DETERMINISM_CHECKS)
  88. /// check an array of objects
  89. template<typename TYPE>
  90. static HK_FORCE_INLINE void HK_CALL checkMt( const TYPE* object, int numObjects = 1 ) { getInstance().checkImpl( object, sizeof(TYPE ) * numObjects ); }
  91. /// check a simple type object
  92. template<typename TYPE>
  93. static HK_FORCE_INLINE void HK_CALL checkMt( const TYPE& object ) { getInstance().checkImpl( &object, sizeof(TYPE )); }
  94. static void HK_CALL initThread() { initThreadImpl(); }
  95. static void HK_CALL quitThread() { quitThreadImpl(); }
  96. static void HK_CALL workerThreadStartFrame(hkBool isPrimaryWorkerThread) { getInstance().workerThreadStartFrameImpl(isPrimaryWorkerThread); }
  97. static void HK_CALL workerThreadFinishFrame() { getInstance().workerThreadFinishFrameImpl(); }
  98. static void HK_CALL registerAndStartJob(Fuid& jobFuid) { getInstance().registerAndStartJobImpl(jobFuid); }
  99. static void HK_CALL finishJob(Fuid& jobFuid) { getInstance().finishJobImpl(jobFuid); }
  100. static void HK_CALL combineRegisteredJobs() { getInstance().combineRegisteredJobsImpl(); }
  101. static void HK_CALL extractRegisteredJobs() { getInstance().extractRegisteredJobsImpl(); }
  102. static void HK_CALL clearRegisteredJobs() { getInstance().clearRegisteredJobsImpl(); }
  103. # else
  104. template<typename TYPE> static HK_ALWAYS_INLINE void HK_CALL checkMt( const TYPE* object, int numObjects = 1 ) { }
  105. template<typename TYPE> static HK_ALWAYS_INLINE void HK_CALL checkMt( const TYPE& object ) { }
  106. static HK_ALWAYS_INLINE void HK_CALL initThread() {  }
  107. static HK_ALWAYS_INLINE void HK_CALL quitThread() {  }
  108. static HK_ALWAYS_INLINE void HK_CALL workerThreadStartFrame(hkBool isPrimaryWorkerThread){  }
  109. static HK_ALWAYS_INLINE void HK_CALL workerThreadFinishFrame() {  }
  110. static HK_ALWAYS_INLINE void HK_CALL registerAndStartJob(Fuid& jobFuid) {  }
  111. static HK_ALWAYS_INLINE void HK_CALL finishJob(Fuid& jobFuid) {  }
  112. static HK_ALWAYS_INLINE void HK_CALL combineRegisteredJobs() {  }
  113. static HK_ALWAYS_INLINE void HK_CALL extractRegisteredJobs() {  }
  114. static HK_ALWAYS_INLINE void HK_CALL clearRegisteredJobs() {  }
  115. # endif
  116. static void HK_CALL initThreadImpl();
  117. static void HK_CALL quitThreadImpl();
  118. void synchStreamsImpl();
  119. void workerThreadStartFrameImpl(hkBool isPrimaryWorkerThread);
  120. void workerThreadFinishFrameImpl();
  121. void  registerAndStartJobImpl(Fuid& jobFuid);
  122. void  finishJobImpl(Fuid& jobFuid);
  123. void  combineRegisteredJobsImpl();
  124. void  extractRegisteredJobsImpl();
  125. void  clearRegisteredJobsImpl();
  126. void checkImpl(const void* object, int size);
  127. /// Call this function at the end of your write/check run. This closes the open files
  128. void finish();
  129. public:
  130. enum Mode
  131. {
  132. MODE_IDLE,
  133. MODE_WRITE,
  134. MODE_COMPARE
  135. };
  136. Mode m_mode;
  137. hkBool m_inSingleThreadedCode;
  138. hkIstream* m_sharedInputStream;
  139. hkOstream* m_sharedOutputStream;
  140. hkIstream* m_primaryWorkerThreadInputStream;
  141. hkOstream* m_primaryWorkerThreadOutputStream;
  142. int m_primaryWorkerThreadJobInfoIdx;
  143. hkCriticalSection* m_shared;
  144. struct JobInfo
  145. {
  146. HK_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( HK_MEMORY_CLASS_BASE_CLASS, hkCheckDeterminismUtil::JobInfo );
  147. Fuid   m_jobFuid;
  148. // This is the data. In multi threaded mode, the thread-local m_input/outputStreams connect to the corresponding hkArray.
  149. // This array is resizable, therefore it has to point to the data array.
  150. hkArray<char>* m_data; // for write
  151. hkBool   m_isOpen;
  152. };
  153. hkArray<JobInfo> m_registeredJobs;
  154. hkBool m_writingStFromWorker;
  155. };
  156. #endif // HKBASE_HKDEBUGUTIL_CHECK_DETERMINISM_UTIL_H
  157. /*
  158. * Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20090216)
  159. * Confidential Information of Havok.  (C) Copyright 1999-2009
  160. * Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  161. * Logo, and the Havok buzzsaw logo are trademarks of Havok.  Title, ownership
  162. * rights, and intellectual property rights in the Havok software remain in
  163. * Havok and/or its suppliers.
  164. * Use of this software for evaluation purposes is subject to and indicates
  165. * acceptance of the End User licence Agreement for this product. A copy of
  166. * the license is included with this software and is also available at www.havok.com/tryhavok.
  167. */