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

其他游戏

开发平台:

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_HKMEMORY_H
  9. #define HKBASE_HKMEMORY_H
  10. #include <Common/Base/Memory/MemoryClasses/hkMemoryClassDefinitions.h>
  11. class hkOstream;
  12. class hkThreadMemory;
  13. #include <Common/Base/Config/hkConfigMemory.h>
  14. /// A struct holding memory allocation information
  15. struct hkMemoryStatistics
  16. {
  17.         /// Infinite as far as the memory system is concerned.
  18.     static const hk_size_t INFINITE_SIZE = (hk_size_t(0)-1);
  19.         /// Total amount of allocated memory. Allocated memory means that it is 'owned' by the hkMemory reporting it -
  20.         /// but the actual memory inside may be available or used. Thus m_used+m_available = m_allocated.
  21.     hk_size_t m_allocated;
  22.         /// Total used memory
  23.     hk_size_t m_used;
  24.         /// Total available from the _allocated_ memory. This is NOT the total amount of memory that is potentially available,
  25.         /// only the amount that remains available from what has been allocated.
  26.     hk_size_t m_available;
  27.         /// The approx total amount of memory that is available. The value is the amount of available memory (m_available)
  28.         /// plus the approx amount of memory that is potentially available but not yet allocated.
  29.         /// Depending on the allocator being used, this value may be meaningless. For example for an allocator with virtual memory
  30.         /// the 'total amount of available' is somewhat meaningless. In those scenarios, m_totalMemory will be INFINITE_SIZE
  31.     hk_size_t m_totalAvailable;
  32.         /// Largest block available. On some memory allocators this is meaningless (for example with virtual memory). In that
  33.         /// case this will be set to INFINITE_SIZE
  34.     hk_size_t m_largestBlock;
  35. HK_DECLARE_SYSTEM_ALLOCATOR();
  36. };
  37.     /// This listener can be used to inform you application about low memory situations within the memory manager.
  38.     /// Ideally on getting the cannotAllocate call, you can free up resources such that an allocation can be made.
  39.     /// If an allocation still isn't possible a call to allocationFailure will be made. The memory the hkMemory
  40.     /// should ideally then return HK_NULL to indicate a successful allocation did not complete.
  41.     /// You do not need to call the garbage collector in this call, as the garbage collector will be run
  42.     /// after the call to cannotAllocate is made.
  43.     /// If in order to free some memory you need some memory you can call garbageCollect, but garbage collection
  44.     /// whilst not slow, isn't that nippy either, so trying to minimise your collects is probably wise.
  45. class hkLimitedMemoryListener
  46. {
  47. public:
  48. HK_DECLARE_SYSTEM_ALLOCATOR();
  49. virtual ~hkLimitedMemoryListener(){}
  50.         /// Called when a request is denied. An implementation can free up memory, and on
  51.         /// returning from this call the allocator will try and allocate again.
  52.     virtual void cannotAllocate(hkMemory* mem,hk_size_t size) =0;
  53.         /// This is called when the allocator has given up allocating. Generally this will be called after
  54.         /// a call to cannotAllocate, although that is not a requirement of an implementaion.
  55.     virtual void allocationFailure(hkMemory* mem,hk_size_t size) = 0;
  56. };
  57. /// Used to traverse over all of the memory.
  58. /// start is the start of a block
  59. /// size is the size of the block in bytes (note the size may be larger than requested in an allocation)
  60. /// If allocated is true then the block is allocated, else its free
  61. /// pool identifies which 'pool' a block of memory belongs to. What that means is implementation specific
  62. /// param is the parameter passed into the memory walking method
  63. typedef void (HK_CALL *hkMemoryWalkCallback)(void* start, hk_size_t size,hkBool allocated,int pool,void* param);
  64. /// All memory allocations in Havok are handled through an instance of this class.
  65. /// Note that all allocations greater than 8 bytes should be 16 byte aligned.
  66. /// Allocations of 8 bytes or less should be aligned to 8 bytes.
  67. /// We distinguish between allocations where the size is explicitly
  68. /// stored or not stored. See the hkBase user guide for more details.
  69. class hkMemory
  70. {
  71. public:
  72. HK_DECLARE_SYSTEM_ALLOCATOR();
  73. friend class hkThreadMemory;
  74. enum 
  75. {
  76. DEFAULT_MAX_NUM_ELEMS_ON_THREAD_MEMORY_FREE_LIST = 16,
  77. };
  78. /// Initialize the reference count to 1.
  79. /// param maxNumElemsOnThreadMemoryFreeList: specifies how many objects can be stored on hkThreadMemory's free list
  80. /// before those blocks are given back to the main memory manager.
  81. /// If you set maxNumElemsOnThreadMemoryFreeList to 0, you effectively disable hkThreadMemory's
  82. /// memory manager.
  83. hkMemory( int maxNumElemsOnThreadMemoryFreeList = DEFAULT_MAX_NUM_ELEMS_ON_THREAD_MEMORY_FREE_LIST );
  84. /// Cleanup.
  85. virtual ~hkMemory();
  86. /// Allocate nblocks of nbytes. This is equivalent to nblocks calls to
  87. /// allocateChunk but is more lock friendly.
  88. virtual void allocateChunkBatch(void** blocksOut, int nblocks, int nbytes, HK_MEMORY_CLASS cl) = 0;
  89. /// Deallocate nblocks of nbytes. This is equivalent to nblocks calls to
  90. /// deallocateChunk but is more lock friendly.
  91. virtual void deallocateChunkBatch(void** blocksOut, int nblocks, int nbytes, HK_MEMORY_CLASS cl) = 0;
  92. /// Allocates a fixed size piece of memory, aligned to 16 bytes.
  93. /// Allocations of 8 bytes or less are aligned to 8 bytes.
  94. /// Note that the size is not stored and must be supplied when deallocating.
  95. virtual void* allocateChunk( int nbytes, HK_MEMORY_CLASS cl) = 0;
  96. /// Deallocates a piece of memory that has been allocated by allocateChunk
  97. virtual void deallocateChunk( void*, int nbytes, HK_MEMORY_CLASS cl ) = 0;
  98. /// Allocates a block of size nbytes of fast runtime memory
  99. /// If a matching block is available this function will return it.
  100. /// If no matching block could be found this function will allocate a new block and issue a warning,
  101. /// add it to its managed array of blocks and return a pointer to it.
  102. ///
  103. /// General info on fast runtime blocks:
  104. /// Regular stack memory is not working properly in a multi-threaded environment. To cater to the need for
  105. /// fast memory allocations during simulation, the concept of dedicated runtime memory blocks (working
  106. /// as a stack memory replacement) has been devised.
  107. /// Runtime block functions provide access to very fast memory allocation by internally
  108. /// storing an array of preallocated memory blocks that are re-used on the fly as soon
  109. /// as they have been declared available again by explicitly deallocating them. New
  110. /// allocations are only performed if no available memory block of matching size could
  111. /// be found in the internal array of managed block.
  112. /// Internally these runtime blocks are only used inside the simulation (i.e. during a call to
  113. /// stepDeltaTime() or stepProcessMt()) and can therefore be used freely outside by the user.
  114. virtual void* allocateRuntimeBlock(int nbytes, HK_MEMORY_CLASS cl) = 0;
  115. /// Deallocates a block of fast runtime memory that has been allocated by allocateRuntimeBlock()
  116. /// For more information on runtime blocks see allocateRuntimeBlock()
  117. virtual void deallocateRuntimeBlock(void*, int nbytes, HK_MEMORY_CLASS cl) = 0;
  118. /// Preallocates a fast runtime memory block of size nbytes
  119. /// For more information on runtime blocks see allocateRuntimeBlock()
  120. virtual void preAllocateRuntimeBlock(int nbytes, HK_MEMORY_CLASS cl) = 0;
  121. /// This allows the user to provide his own block(s) of memory for fast runtime memory
  122. /// Note that memory blocks that have been provided by the user will not be deallocated by a call to
  123. /// freeRuntimeBlocks(). The user has to take care of deallocation himself.
  124. /// For more information on runtime blocks see allocateRuntimeBlock()
  125. virtual void provideRuntimeBlock(void*, int nbytes, HK_MEMORY_CLASS cl) = 0;
  126. /// Deallocate all fast runtime memory blocks that are still allocated and that have NOT been provided
  127. /// by the user (by using provideRuntimeBlock())
  128. /// For more information on runtime blocks see allocateRuntimeBlock()
  129. virtual void freeRuntimeBlocks() = 0;
  130. /// See hkPoolMemory::reservePagesFromSystemMemory()
  131. virtual void reservePagesFromSystemMemory( int numBytes ) {}
  132.             /// Depending on the implementation, will try and free up memory resources to make more memory available.
  133.             /// Concretely in many implementations, lists of small sized blocks are kept, so they can be made available
  134.             /// rapidly. These small blocks although not used, may stop larger blocks being allocated, the collector will
  135.             /// free up such pages so they can be used as part of other allocations.
  136.         virtual void garbageCollect() {}
  137.             /// Optimizing allows the memory manager to look the memory usage optimize its usage - for performance
  138.             /// primarily. The process is similar to a garbage collect in terms of finding memory thats free,
  139.             /// an optimize can decide to make this memory available for a commonly used block size for example.
  140.             /// You shouldn't call this method every frame, but calling between levels may help overall memory
  141.             /// usage. In terms of cost, doing an optimize requires a similar amount of work to a garbage collection.
  142.         virtual void optimize() {}
  143. /// See hkPoolMemory::releaseUnusedPagesToSystemMemory()
  144. virtual void releaseUnusedPagesToSystemMemory( void ) {}
  145. /// Prints some statistics to the specified console.
  146. virtual void printStatistics(hkOstream* c) = 0;
  147. /// Find the memory rounded up by the memory allocator for a requested memory allocation
  148. virtual int getAllocatedSize( int size );
  149. /// Returns true if this is a debug memory manager, false otherwise
  150. virtual bool isDebugMemory(){ return false; }
  151.             /// Work out memory statistics. This function tries to work out fairly accurately details about memory usage -
  152.             /// this functions performance may not be great depending on the underlying implementation.
  153.             /// See hkMemoryStatisticcs for details of the information returned.
  154.             /// NOTE! That if you have a memory limit set (via setMemoryLimit) the values returned will reflect that limit
  155.             /// you must have the limit set to zero if you want to find out the 'true' memory statistics.
  156.         virtual void calculateStatistics(hkMemoryStatistics& stats ) =0;
  157.             /// There are two styles of limit in the memory allocator, a soft limit and a hard limit.
  158.             /// If the soft limit is exceeded it will _NOT_ stop an allocation being performed if it can be performed.
  159.             /// The way to test to see if the soft limit has been exceeded is to call hasMemoryAvailable, which will
  160.             /// return false if the soft limit has been passed.
  161.             /// The other type of limit is a 'hard' limit. The hard limit cannot be passed - if you try and allocate
  162.             /// past the hard limit allocation will fail and HK_NULL will be returned. Passing the hard limit is also
  163.             /// what will produce calls to the hkLimitedMemoryListener. There is no listener mechanism around the
  164.             /// soft limit, for performance reasons.
  165.             /// Allow the setting of a memory usage limit (in bytes). Depending on the implementation the limit
  166.             /// may or may not be honored. Look at the docs on specific implementations to see if memory limiting
  167.             /// is supported. If limiting is not supported the method will have no effect. If the memory requested was
  168.             /// unfeasibly low (for example more than that amount of memory has already been allocated) the
  169.             /// actual setting does not change. Check getMemoryLimit to see if the change has been accepted.
  170.             /// Setting the limit to 0, will set the limit to as large as possible
  171.         virtual void setMemoryHardLimit(hk_size_t maxMemory) { }
  172.             /// Returns what the limit is set to (in bytes). If there is no limit the method returns 0.
  173.         virtual hk_size_t getMemoryHardLimit() { return 0; }
  174.             /// set a soft memory limit. Setting 0 will mean there is no soft limit.
  175.             /// See setMemoryHardLimit for a description of the difference between a soft and hard limit
  176.         virtual void setMemorySoftLimit(hk_size_t maxMemory) { }
  177.             /// Returns what the soft memory limit is. 0 means there is no soft memory limit.
  178.         virtual hk_size_t getMemorySoftLimit() { return 0; }
  179.             /// Set the limited memory listener. May not be implemented on all implementations - you can check
  180.             /// by doing a get, if it is HK_NULL and you tried to set it to something, support for the listener isn't implemented
  181.             /// on this platform.
  182.         virtual void setLimitedMemoryListener(hkLimitedMemoryListener* listener) {}
  183.             /// Get the limited memory listener. Not all memory systems support listeners.
  184.         virtual hkLimitedMemoryListener* getLimitedMemoryListener() { return HK_NULL; }
  185.             /// Returns true if an amount of memory of at least 'size' is available. Why not just have a method that returns
  186.             /// the amount of memory available? Because with some allocators its meaningless - for when you have virtual
  187.             /// memory, and because the implementation can decide broadly what 'enough memory' means - as it has internal
  188.             /// knowledge about how memory works. This method is designed to be fast so can be called rapidly if needs be,
  189.             /// but recommended use would be to call infrequently and check that larger allocations are available.
  190.             /// Passing in size as zero well return true if some 'nominal' amount of memory required for normal function
  191.             /// is available.
  192.         virtual hkBool hasMemoryAvailable(hk_size_t size) { return true; }
  193. /// Some implementations (the DebugMemory for instance) can do checks on the current
  194. /// allocated pool. If the implementation does not support the check it will just return true.
  195. virtual hkBool isOk() const;
  196. /// Using the hkDebugMemory implementation you can use this function to search for the originally allocated memory block
  197. /// within which the supplied memory block is located. This function returns the originally allocated memory block's base
  198. /// address. It will assert if it cannot find a matching block.
  199. virtual void* findBaseAddress(void* p, int nbytes) { return HK_NULL; }
  200. /// Using the hkDebugMemory you can explicitly lock allocated memory. Upon freeing a memory block this lock counter will be
  201. /// checked and the debug memory will assert if there is still a lock left.
  202. virtual void lockBlock(void* p) {}
  203. /// Unlock memory in hkDebugMemory.
  204. virtual void unlockBlock(void* p) {}
  205.             /// Traverses all of the memory used by the subsystem (allocated and free). The order that allocations
  206.             /// are returned is undefined. Not all memory allocators can walk memory - if an implementation cannot
  207.             /// it will return HK_FAILURE from this method.
  208.         virtual hkResult walkMemory(hkMemoryWalkCallback callback,void* param) { return HK_FAILURE; }
  209. /// Status of the memory manager.
  210. enum MemoryState
  211. {
  212. MEMORY_STATE_OK,
  213. MEMORY_STATE_OUT_OF_MEMORY
  214. };
  215. MemoryState m_memoryState;
  216. int m_criticalMemoryLimit;
  217.         int m_memoryUsed;
  218. static inline hkMemory& HK_CALL getInstance();
  219. static void HK_CALL replaceInstance(hkMemory* m);
  220. HK_FORCE_INLINE void addReference();
  221. HK_FORCE_INLINE void removeReference();
  222. HK_FORCE_INLINE int getMaxNumElemsOnThreadMemoryFreeList() const;
  223. /// Constant values used in debug modes.
  224. enum MemoryFill
  225. {
  226. /// For guard bytes before and after allocations.
  227. MEMORY_FILL_GUARD_AREA = 0xFD,
  228. /// Free memory owned by the memory manager.
  229. MEMORY_FILL_FREE_SPACE = 0xDD,
  230. /// Newly allocated memory to be returned.
  231. MEMORY_FILL_RETURNED_TO_USER = 0xCD
  232. };
  233. protected:
  234. static hkMemory* s_instance;
  235. int m_referenceCount;
  236. // This value is used by all hkThreadMemory instances
  237. const int m_maxNumElemsOnThreadMemoryFreeList ;
  238. struct BigBlockData
  239. {
  240. hkBool m_available;
  241. int m_size;
  242. void* m_memory;
  243. HK_MEMORY_CLASS m_class;
  244. hkBool m_providedByOutside;
  245. };
  246. enum { BIG_BLOCKS_SLOTS=128 };
  247. int m_numValidBigBlocks;
  248. BigBlockData m_bigBlockDataArray[BIG_BLOCKS_SLOTS];
  249. public:
  250. /// Value to fill guard bytes before and after allocations. By default, hkMemory::MEMORY_FILL_GUARD_AREA.
  251. static hkInt32 s_fillGuardArea;
  252. /// Value to fill free memory owned by the memory manager. By default, hkMemory::MEMORY_FILL_FREE_SPACE.
  253. static hkInt32 s_fillFreeSpace;
  254. /// Value to fill allocated memory to be returned. By default, hkMemory::MEMORY_FILL_RETURNED_TO_USER.
  255. static hkInt32 s_fillReturnedToUser;
  256. };
  257. hkMemory& HK_CALL hkMemory::getInstance()
  258. {
  259. return *s_instance;
  260. }
  261. void hkMemory::removeReference()
  262. {
  263. --m_referenceCount;
  264. if(m_referenceCount==0)
  265. {
  266. delete this;
  267. }
  268. }
  269. void hkMemory::addReference()
  270. {
  271. ++m_referenceCount;
  272. }
  273. int hkMemory::getMaxNumElemsOnThreadMemoryFreeList() const
  274. {
  275. return m_maxNumElemsOnThreadMemoryFreeList;
  276. }
  277. #endif // HKBASE_HKMEMORY_H
  278. /*
  279. * Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20090216)
  280. * Confidential Information of Havok.  (C) Copyright 1999-2009
  281. * Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  282. * Logo, and the Havok buzzsaw logo are trademarks of Havok.  Title, ownership
  283. * rights, and intellectual property rights in the Havok software remain in
  284. * Havok and/or its suppliers.
  285. * Use of this software for evaluation purposes is subject to and indicates
  286. * acceptance of the End User licence Agreement for this product. A copy of
  287. * the license is included with this software and is also available at www.havok.com/tryhavok.
  288. */