1 #ifndef vtkExodusIICache_h 2 #define vtkExodusIICache_h 3 4 // ============================================================================ 5 // The following classes define an LRU cache for data arrays 6 // loaded by the Exodus reader. Here's how they work: 7 // 8 // The actual cache consists of two STL containers: a set of 9 // cache entries (vtkExodusIICacheEntry) and a list of 10 // cache references (vtkExodusIICacheRef). The entries in 11 // these containers are sorted for fast retrieval: 12 // 1. The cache entries are indexed by the timestep, the 13 // object type (edge block, face set, ...), and the 14 // object ID (if one exists). When you call Find() to 15 // retrieve a cache entry, you provide a key containing 16 // this information and the array is returned if it exists. 17 // 2. The list of cache references are stored in "least-recently-used" 18 // order. The least recently referenced array is the first in 19 // the list. Whenever you request an entry with Find(), it is 20 // moved to the back of the list if it exists. 21 // This makes retrieving arrays O(n log n) and popping LRU 22 // entries O(1). Each cache entry stores an iterator into 23 // the list of references so that it can be located quickly for 24 // removal. 25 26 #include "vtkIOExodusModule.h" // For export macro 27 #include "vtkObject.h" 28 29 #include <list> // use for LRU ordering 30 #include <map> // used for cache storage 31 32 class VTKIOEXODUS_EXPORT vtkExodusIICacheKey 33 { 34 public: 35 int Time; 36 int ObjectType; 37 int ObjectId; 38 int ArrayId; vtkExodusIICacheKey()39 vtkExodusIICacheKey() 40 { 41 Time = -1; 42 ObjectType = -1; 43 ObjectId = -1; 44 ArrayId = -1; 45 } vtkExodusIICacheKey(int time,int objType,int objId,int arrId)46 vtkExodusIICacheKey(int time, int objType, int objId, int arrId) 47 { 48 Time = time; 49 ObjectType = objType; 50 ObjectId = objId; 51 ArrayId = arrId; 52 } vtkExodusIICacheKey(const vtkExodusIICacheKey & src)53 vtkExodusIICacheKey(const vtkExodusIICacheKey& src) 54 { 55 Time = src.Time; 56 ObjectType = src.ObjectType; 57 ObjectId = src.ObjectId; 58 ArrayId = src.ArrayId; 59 } 60 vtkExodusIICacheKey& operator=(const vtkExodusIICacheKey& src) = default; match(const vtkExodusIICacheKey & other,const vtkExodusIICacheKey & pattern)61 bool match(const vtkExodusIICacheKey& other, const vtkExodusIICacheKey& pattern) const 62 { 63 if (pattern.Time && this->Time != other.Time) 64 return false; 65 if (pattern.ObjectType && this->ObjectType != other.ObjectType) 66 return false; 67 if (pattern.ObjectId && this->ObjectId != other.ObjectId) 68 return false; 69 if (pattern.ArrayId && this->ArrayId != other.ArrayId) 70 return false; 71 return true; 72 } 73 bool operator<(const vtkExodusIICacheKey& other) const 74 { 75 if (this->Time < other.Time) 76 return true; 77 else if (this->Time > other.Time) 78 return false; 79 if (this->ObjectType < other.ObjectType) 80 return true; 81 else if (this->ObjectType > other.ObjectType) 82 return false; 83 if (this->ObjectId < other.ObjectId) 84 return true; 85 else if (this->ObjectId > other.ObjectId) 86 return false; 87 if (this->ArrayId < other.ArrayId) 88 return true; 89 return false; 90 } 91 }; 92 93 class vtkExodusIICacheEntry; 94 class vtkExodusIICache; 95 class vtkDataArray; 96 97 typedef std::map<vtkExodusIICacheKey, vtkExodusIICacheEntry*> vtkExodusIICacheSet; 98 typedef std::map<vtkExodusIICacheKey, vtkExodusIICacheEntry*>::iterator vtkExodusIICacheRef; 99 typedef std::list<vtkExodusIICacheRef> vtkExodusIICacheLRU; 100 typedef std::list<vtkExodusIICacheRef>::iterator vtkExodusIICacheLRURef; 101 102 class VTKIOEXODUS_EXPORT vtkExodusIICacheEntry 103 { 104 public: 105 vtkExodusIICacheEntry(); 106 vtkExodusIICacheEntry(vtkDataArray* arr); 107 vtkExodusIICacheEntry(const vtkExodusIICacheEntry& other); 108 109 ~vtkExodusIICacheEntry(); 110 GetValue()111 vtkDataArray* GetValue() { return this->Value; } 112 113 protected: 114 vtkDataArray* Value; 115 vtkExodusIICacheLRURef LRUEntry; 116 117 friend class vtkExodusIICache; 118 }; 119 120 class VTKIOEXODUS_EXPORT vtkExodusIICache : public vtkObject 121 { 122 public: 123 static vtkExodusIICache* New(); 124 vtkTypeMacro(vtkExodusIICache, vtkObject); 125 void PrintSelf(ostream& os, vtkIndent indent) override; 126 127 /// Empty the cache 128 void Clear(); 129 130 /// Set the maximum allowable cache size. This will remove cache entries if the capacity is 131 /// reduced below the current size. 132 void SetCacheCapacity(double sizeInMiB); 133 134 /** See how much cache space is left. 135 * This is the difference between the capacity and the size of the cache. 136 * The result is in MiB. 137 */ GetSpaceLeft()138 double GetSpaceLeft() { return this->Capacity - this->Size; } 139 140 /** Remove cache entries until the size of the cache is at or below the given size. 141 * Returns a nonzero value if deletions were required. 142 */ 143 int ReduceToSize(double newSize); 144 145 /// Insert an entry into the cache (this can remove other cache entries to make space). 146 void Insert(vtkExodusIICacheKey& key, vtkDataArray* value); 147 148 /** Determine whether a cache entry exists. If it does, return it -- otherwise return nullptr. 149 * If a cache entry exists, it is marked as most recently used. 150 */ 151 vtkDataArray*& Find(const vtkExodusIICacheKey&); 152 153 /** Invalidate a cache entry (drop it from the cache) if the key exists. 154 * This does nothing if the cache entry does not exist. 155 * Returns 1 if the cache entry existed prior to this call and 0 otherwise. 156 */ 157 int Invalidate(const vtkExodusIICacheKey& key); 158 159 /** Invalidate all cache entries matching a specified pattern, dropping all matches from the 160 * cache. Any nonzero entry in the \a pattern forces a comparison between the corresponding value 161 * of \a key. Any cache entries satisfying all the comparisons will be dropped. If pattern is 162 * entirely zero, this will empty the entire cache. This is useful for invalidating all entries of 163 * a given object type. 164 * 165 * Returns the number of cache entries dropped. 166 * It is not an error to specify an empty range -- 0 will be returned if one is given. 167 */ 168 int Invalidate(const vtkExodusIICacheKey& key, const vtkExodusIICacheKey& pattern); 169 170 protected: 171 /// Default constructor 172 vtkExodusIICache(); 173 174 /// Destructor. 175 ~vtkExodusIICache() override; 176 177 /// Avoid (some) FP problems 178 void RecomputeSize(); 179 180 /// The capacity of the cache (i.e., the maximum size of all arrays it contains) in MiB. 181 double Capacity; 182 183 /// The current size of the cache (i.e., the size of the all the arrays it currently contains) in 184 /// MiB. 185 double Size; 186 187 /** A least-recently-used (LRU) cache to hold arrays. 188 * During RequestData the cache may contain more than its maximum size since 189 * the user may request more data than the cache can hold. However, the cache 190 * is expunged whenever a new array is loaded. Never count on the cache holding 191 * what you request for very long. 192 */ 193 vtkExodusIICacheSet Cache; 194 195 /// The actual LRU list (indices into the cache ordered least to most recently used). 196 vtkExodusIICacheLRU LRU; 197 198 private: 199 vtkExodusIICache(const vtkExodusIICache&) = delete; 200 void operator=(const vtkExodusIICache&) = delete; 201 }; 202 #endif // vtkExodusIICache_h 203