Cache.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /******************************************************************************
  2. Use 'Cache' to quickly access custom data by loading it from specified file.
  3. Once 'Cache' loads a resource, it will keep it in the memory for faster access.
  4. You can also use 'Cache' to access file name of already loaded element.
  5. Objects in 'Cache' containers are stored using 'Memx' container,
  6. which means that the memory address of the elements remains constant as long as the elements exist.
  7. 'Cache' loads the data and stores it forever (as long as the cache lives),
  8. in order to load the data for as long as it is needed, you must use 'CacheElmPtr'.
  9. 'CacheElmPtr' can be treated like a typical pointer, with the exception that when copied or destroyed,
  10. it automatically increases/decreses the reference count of an element inside a cache.
  11. Once the reference count of an element drops to zero, it means that there are no more 'CacheElmPtr'
  12. pointers referencing the data, and the data is released.
  13. Engine uses the 'Cache' class to store many types of data, for example:
  14. 'Images' - cache for images , with 'ImagePtr' typedef for the 'CacheElmPtr' template pointer
  15. 'Materials' - cache for materials, with 'MaterialPtr' typedef for the 'CacheElmPtr' template pointer
  16. 'Meshes' - cache for meshes , with 'MeshPtr' typedef for the 'CacheElmPtr' template pointer
  17. ..
  18. /******************************************************************************/
  19. enum CACHE_MODE : Byte // Cache Mode
  20. {
  21. CACHE_EXIT , // load data, Exit on fail
  22. CACHE_NULL , // load data, null on fail
  23. CACHE_DUMMY , // load data, dummy on fail (pointer to empty data with correct path, initialized with constructor but without the 'load' method)
  24. CACHE_ALL_NULL , // don't load data, always return null
  25. CACHE_ALL_DUMMY , // don't load data, always return dummy (pointer to empty data with correct path, initialized with constructor but without the 'load' method)
  26. CACHE_DUMMY_NULL, // don't load data, return dummy (pointer to empty data with correct path, initialized with constructor but without the 'load' method) if a file exists at specified path, if a file does not exist then null is returned
  27. };
  28. #if EE_PRIVATE
  29. enum CACHE_ELM_FLAG // Cache Element Flag
  30. {
  31. CACHE_ELM_DUMMY =1<<0, // if element was not found but created anyway
  32. CACHE_ELM_LOADING =1<<1, // if element is still being loaded (for example, during loading of element A, it loads element B, which tries to access A which didn't finish loading yet)
  33. CACHE_ELM_STD_PTR =1<<2, // if element was accessed by standard C++ pointer (not reference counted pointer)
  34. CACHE_ELM_DELAY_REMOVE=1<<3, // if element reached zero references and was added to the '_delay_remove'
  35. };
  36. #endif
  37. /******************************************************************************/
  38. // CACHE
  39. /******************************************************************************/
  40. T1(TYPE) struct Cache : _Cache // Cache - container for dynamically loaded data, used for fast accessing data through file name, 'Cache' is multi-threaded safe
  41. {
  42. struct Elm : _Cache::Elm
  43. {
  44. TYPE data;
  45. Desc desc;
  46. };
  47. // manage
  48. CACHE_MODE mode (CACHE_MODE mode); // set cache mode, returns previous mode
  49. Cache& caseSensitive (Bool sensitive); // set if cache should use case sensitive paths for accessing resources, default=false
  50. Cache& delayRemove (Flt time ); // set amount of time (in seconds) after which unused elements are removed from cache (<=0 value specifies immediate unloading), default=0
  51. Cache& delayRemoveNow( ); // immediately remove all elements marked for delay removal at a later time to free as much memory as possible
  52. Cache& delayRemoveInc( ); // increase the cache "delay remove" counter thanks to which elements will not be immediately removed when they're no longer referenced, 'delayRemoveDec' should be called after this method
  53. Cache& delayRemoveDec( ); // decrease the cache "delay remove" counter thanks to which elements will not be immediately removed when they're no longer referenced, this should be called after 'delayRemoveInc', once the counter goes back to zero then all non referenced elements will be removed
  54. // get object and store it forever (as long as the Cache lives)
  55. TYPE* find (C Str &file, CChar *path=null); // find object by its file name , don't load if not found, null on fail
  56. TYPE* find (C UID &id , CChar *path=null); // find object by its file name ID, don't load if not found, null on fail
  57. TYPE* get (C Str &file, CChar *path=null); // get object by its file name , load if not found, null on fail
  58. TYPE* get (C UID &id , CChar *path=null); // get object by its file name ID, load if not found, null on fail
  59. TYPE* operator()(C Str &file, CChar *path=null); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected)
  60. TYPE* operator()(C UID &id , CChar *path=null); // require object by its file name ID, load if not found, Exit on fail (unless different CACHE_MODE selected)
  61. // get object file name (this will return pointer to internally stored file name assuming that the object is stored in this Cache)
  62. CChar* name(C TYPE *data, CChar *path=null)C; // get object file name, null on fail
  63. template<Cache<TYPE> &CACHE> CChar* name(C CacheElmPtr<TYPE,CACHE> &data, CChar *path=null)C {return name(data(), path);} // get object file name, null on fail
  64. // get object file name ID (this will return ID of the object file name assuming that the object is stored in the cache and its file name was created using 'EncodeFileName')
  65. UID id(C TYPE *data)C; // get object file name ID, 'UIDZero' on fail
  66. template<Cache<TYPE> &CACHE> UID id(C CacheElmPtr<TYPE,CACHE> &data)C {return id(data());} // get object file name ID, 'UIDZero' on fail
  67. // get
  68. Int elms()C; // get number of elements in container
  69. Bool contains(C TYPE *data )C; // check if cache contains this object
  70. template<Cache<TYPE> &CACHE> Bool contains(C CacheElmPtr<TYPE,CACHE> &data )C {return contains(data() );} // check if cache contains this object
  71. Int ptrCount(C TYPE *data )C; // check if cache contains this object and return current number of active pointer references to it, -1 is returned if object is not stored in this cache
  72. template<Cache<TYPE> &CACHE> Int ptrCount(C CacheElmPtr<TYPE,CACHE> &data )C {return ptrCount(data() );} // check if cache contains this object and return current number of active pointer references to it, -1 is returned if object is not stored in this cache
  73. Bool dummy (C TYPE *data )C; // check if cache contains this object and it's a dummy (it was not loaded but created as empty)
  74. template<Cache<TYPE> &CACHE> Bool dummy (C CacheElmPtr<TYPE,CACHE> &data )C {return dummy (data() );} // check if cache contains this object and it's a dummy (it was not loaded but created as empty)
  75. void dummy (C TYPE *data, Bool dummy) ; // if cache contains this object then set its dummy state (this can be used for example if object was first loaded as a dummy, but then you've downloaded/generated/saved its data, and now need to update the dummy state)
  76. template<Cache<TYPE> &CACHE> void dummy (C CacheElmPtr<TYPE,CACHE> &data, Bool dummy) { T.dummy (data(), dummy);} // if cache contains this object then set its dummy state (this can be used for example if object was first loaded as a dummy, but then you've downloaded/generated/saved its data, and now need to update the dummy state)
  77. // operations
  78. void lock ( )C; // lock elements container, unlock must be called after locking container
  79. C Desc& lockedDesc(Int i)C; // access i-th element desc from container, this can be used after locking and before unlocking the container
  80. TYPE& lockedData(Int i) ; // access i-th element data from container, this can be used after locking and before unlocking the container
  81. C TYPE& lockedData(Int i)C; // access i-th element data from container, this can be used after locking and before unlocking the container
  82. void unlock ( )C; // unlock elements container, this must be called after locking the container
  83. #if EE_PRIVATE
  84. void canBeRemoved(Bool CanBeRemoved(C TYPE &data)) {lock(); _can_be_removed=(Bool(*)(CPtr))CanBeRemoved; unlock();}
  85. #endif
  86. void removeData(C TYPE *data); // manually remove object from cache, this is ignored for objects which still are accessed by some CacheElmPtr's
  87. void update(); // update cache to process all delay removed elements
  88. T1(EXTENDED) Cache& replaceClass(); // replace the type of class stored in the container, all elements are automatically removed before changing the type of the class, the new type must be extended from the base 'TYPE' (if you're receiving a compilation error pointing to this method this means that the new class isn't extended from the base class)
  89. void setLoadUser(Ptr user); // if this method is called, then elements will be loaded using their "Bool load(C Str &name, Ptr user)" method instead, with 'user' as its parameter
  90. Cache& operator=(C Cache &src); // create from 'src'
  91. Cache& clear(); // remove all elements
  92. Cache& del (); // remove all elements and free helper memory
  93. explicit Cache(CChar8 *name=null, Int block_elms=64); // 'name'=cache name (this value is optional, it will be used when displaying an error message when cache element failed to load)
  94. };
  95. /******************************************************************************/
  96. // CACHE ELEMENT POINTER
  97. /******************************************************************************/
  98. template<typename TYPE, Cache<TYPE> &CACHE> struct CacheElmPtr // Cache Element Pointer - can hold a reference to a TYPE based object in the CACHE cache, number of active references for a given object is stored in the cache
  99. {
  100. // operators
  101. TYPE* operator () ( )C {return T._data ;} // access the data, you can use the returned pointer as long as this 'CacheElmPtr' object exists and not modified
  102. TYPE* operator -> ( )C {return T._data ;} // access the data, you can use the returned pointer as long as this 'CacheElmPtr' object exists and not modified
  103. TYPE& operator * ( )C {return *T._data ;} // access the data, you can use the returned reference as long as this 'CacheElmPtr' object exists and not modified
  104. Bool operator == ( null_t )C {return T._data==null ;} // if pointers are equal
  105. Bool operator != ( null_t )C {return T._data!=null ;} // if pointers are different
  106. Bool operator == (C TYPE *data)C {return T._data==data ;} // if pointers are equal
  107. Bool operator != (C TYPE *data)C {return T._data!=data ;} // if pointers are different
  108. Bool operator == (C CacheElmPtr &eptr)C {return T._data==eptr._data;} // if pointers are equal
  109. Bool operator != (C CacheElmPtr &eptr)C {return T._data!=eptr._data;} // if pointers are different
  110. operator Bool( )C {return T._data!=null ;} // if pointer is valid
  111. // get object file name (this will return pointer to internally stored file name assuming that the object is stored in the cache)
  112. CChar* name(CChar *path=null)C; // get object file name, null on fail
  113. // get object file name ID (this will return ID of the object file name assuming that the object is stored in the cache and its file name was created using 'EncodeFileName')
  114. UID id()C; // get object file name ID, 'UIDZero' on fail
  115. // get
  116. Bool dummy( )C; // check if this object is a dummy (it was not loaded but created as empty)
  117. void dummy(Bool dummy) ; // set dummy state for this object (this can be used for example if object was first loaded as a dummy, but then you've downloaded/generated/saved its data, and now need to update the dummy state)
  118. // operations
  119. CacheElmPtr& clear ( ); // clear the pointer to null , this automatically decreases the reference count of current data
  120. CacheElmPtr& operator=( null_t ); // clear the pointer to null , this automatically decreases the reference count of current data
  121. CacheElmPtr& operator=( TYPE * data); // set pointer to 'data', this automatically decreases the reference count of current data and increases the reference count of the new data
  122. CacheElmPtr& operator=(C CacheElmPtr & eptr); // set pointer to 'eptr', this automatically decreases the reference count of current data and increases the reference count of the new data
  123. CacheElmPtr& operator=( CacheElmPtr &&eptr); // set pointer to 'eptr', this automatically decreases the reference count of current data and increases the reference count of the new data
  124. // get object and store it temporarily (as long as it is referenced by at least one 'CacheElmPtr')
  125. CacheElmPtr& find (CChar *file, CChar *path=null); // find object by its file name , don't load if not found, null on fail
  126. CacheElmPtr& find (CChar8 *file, CChar *path=null); // find object by its file name , don't load if not found, null on fail
  127. CacheElmPtr& find (C Str &file, CChar *path=null); // find object by its file name , don't load if not found, null on fail
  128. CacheElmPtr& find (C Str8 &file, CChar *path=null); // find object by its file name , don't load if not found, null on fail
  129. CacheElmPtr& find (C UID &id , CChar *path=null); // find object by its file name ID, don't load if not found, null on fail
  130. CacheElmPtr& get (CChar *file, CChar *path=null); // get object by its file name , load if not found, null on fail
  131. CacheElmPtr& get (CChar8 *file, CChar *path=null); // get object by its file name , load if not found, null on fail
  132. CacheElmPtr& get (C Str &file, CChar *path=null); // get object by its file name , load if not found, null on fail
  133. CacheElmPtr& get (C Str8 &file, CChar *path=null); // get object by its file name , load if not found, null on fail
  134. CacheElmPtr& get (C UID &id , CChar *path=null); // get object by its file name ID, load if not found, null on fail
  135. CacheElmPtr& require (CChar *file, CChar *path=null); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected)
  136. CacheElmPtr& require (CChar8 *file, CChar *path=null); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected)
  137. CacheElmPtr& require (C Str &file, CChar *path=null); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected)
  138. CacheElmPtr& require (C Str8 &file, CChar *path=null); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected)
  139. CacheElmPtr& require (C UID &id , CChar *path=null); // require object by its file name ID, load if not found, Exit on fail (unless different CACHE_MODE selected)
  140. CacheElmPtr& operator=(CChar *file ); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected), works exactly the same as 'require' method, however without the option of specifying additional 'path'
  141. CacheElmPtr& operator=(CChar8 *file ); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected), works exactly the same as 'require' method, however without the option of specifying additional 'path'
  142. CacheElmPtr& operator=(C Str &file ); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected), works exactly the same as 'require' method, however without the option of specifying additional 'path'
  143. CacheElmPtr& operator=(C Str8 &file ); // require object by its file name , load if not found, Exit on fail (unless different CACHE_MODE selected), works exactly the same as 'require' method, however without the option of specifying additional 'path'
  144. CacheElmPtr& operator=(C UID &id ); // require object by its file name ID, load if not found, Exit on fail (unless different CACHE_MODE selected), works exactly the same as 'require' method, however without the option of specifying additional 'path'
  145. // constructors / destructors
  146. CacheElmPtr( null_t=null ); // initialize the pointer with null
  147. CacheElmPtr( TYPE * data); // initialize the pointer with 'data', this automatically increases the reference count of the 'data'
  148. CacheElmPtr(C CacheElmPtr & eptr); // initialize the pointer with 'eptr', this automatically increases the reference count of the 'eptr'
  149. CacheElmPtr( CacheElmPtr &&eptr); // initialize the pointer with 'eptr', this automatically increases the reference count of the 'eptr'
  150. CacheElmPtr(C Str & file); // initialize the pointer with 'file', this automatically increases the reference count of the 'file', works exactly the same as 'operator=(C Str &file)', require object, load if not found, Exit on fail (unless different CACHE_MODE selected)
  151. CacheElmPtr(C Str8 & file); // initialize the pointer with 'file', this automatically increases the reference count of the 'file', works exactly the same as 'operator=(C Str8 &file)', require object, load if not found, Exit on fail (unless different CACHE_MODE selected)
  152. CacheElmPtr( CChar * file); // initialize the pointer with 'file', this automatically increases the reference count of the 'file', works exactly the same as 'operator=(CChar *file)', require object, load if not found, Exit on fail (unless different CACHE_MODE selected)
  153. CacheElmPtr( CChar8 * file); // initialize the pointer with 'file', this automatically increases the reference count of the 'file', works exactly the same as 'operator=(CChar8 *file)', require object, load if not found, Exit on fail (unless different CACHE_MODE selected)
  154. CacheElmPtr(C UID & id ); // initialize the pointer with 'id' , this automatically increases the reference count of the 'file', works exactly the same as 'operator=(C UID &id )', require object, load if not found, Exit on fail (unless different CACHE_MODE selected)
  155. ~CacheElmPtr( ); // release the pointer , this automatically decreases the reference count of current data
  156. private:
  157. TYPE *_data;
  158. };
  159. /******************************************************************************/
  160. struct CacheLock // Cache Lock (automatically locks and unlocks the cache at object creation and destruction)
  161. {
  162. explicit CacheLock(C _Cache &cache) : _cache(cache) {_cache. lock();}
  163. ~CacheLock( ) {_cache.unlock();}
  164. private:
  165. C _Cache &_cache;
  166. NO_COPY_CONSTRUCTOR(CacheLock);
  167. };
  168. /******************************************************************************/
  169. #define DECLARE_CACHE(TYPE, cache_name, ptr_name ) extern Cache<TYPE> cache_name ; typedef CacheElmPtr<TYPE, cache_name> ptr_name; // this declares a Cache and a CacheElmPtr in a header, the cache stores 'TYPE' data, the cache name is 'cache_name' and the name for the pointer to elements is 'ptr_name'
  170. #define DEFINE_CACHE(TYPE, cache_name, ptr_name, debug_name) Cache<TYPE> cache_name(debug_name); typedef CacheElmPtr<TYPE, cache_name> ptr_name; // this defines a Cache and a CacheElmPtr in C++ file
  171. #if EE_PRIVATE
  172. #define DEFINE_CACHE_EX(TYPE, cache_name, ptr_name, debug_name, block_elms) Cache<TYPE> cache_name(debug_name, block_elms); typedef CacheElmPtr<TYPE, cache_name> ptr_name; // this defines a Cache and a CacheElmPtr in C++ file
  173. #endif
  174. /******************************************************************************/