|  | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #ifndef sw_LRUCache_hpp | 
|  | #define sw_LRUCache_hpp | 
|  |  | 
|  | #include "Common/Math.hpp" | 
|  |  | 
|  | namespace sw | 
|  | { | 
|  | template<class Key, class Data> | 
|  | class LRUCache | 
|  | { | 
|  | public: | 
|  | LRUCache(int n); | 
|  |  | 
|  | ~LRUCache(); | 
|  |  | 
|  | Data *query(const Key &key) const; | 
|  | Data *add(const Key &key, Data *data); | 
|  |  | 
|  | int getSize() {return size;} | 
|  | Key &getKey(int i) {return key[i];} | 
|  |  | 
|  | private: | 
|  | int size; | 
|  | int mask; | 
|  | int top; | 
|  | int fill; | 
|  |  | 
|  | Key *key; | 
|  | Key **ref; | 
|  | Data **data; | 
|  | }; | 
|  | } | 
|  |  | 
|  | namespace sw | 
|  | { | 
|  | template<class Key, class Data> | 
|  | LRUCache<Key, Data>::LRUCache(int n) | 
|  | { | 
|  | size = ceilPow2(n); | 
|  | mask = size - 1; | 
|  | top = 0; | 
|  | fill = 0; | 
|  |  | 
|  | key = new Key[size]; | 
|  | ref = new Key*[size]; | 
|  | data = new Data*[size]; | 
|  |  | 
|  | for(int i = 0; i < size; i++) | 
|  | { | 
|  | data[i] = nullptr; | 
|  |  | 
|  | ref[i] = &key[i]; | 
|  | } | 
|  | } | 
|  |  | 
|  | template<class Key, class Data> | 
|  | LRUCache<Key, Data>::~LRUCache() | 
|  | { | 
|  | delete[] key; | 
|  | key = nullptr; | 
|  |  | 
|  | delete[] ref; | 
|  | ref = nullptr; | 
|  |  | 
|  | for(int i = 0; i < size; i++) | 
|  | { | 
|  | if(data[i]) | 
|  | { | 
|  | data[i]->unbind(); | 
|  | data[i] = nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | delete[] data; | 
|  | data = nullptr; | 
|  | } | 
|  |  | 
|  | template<class Key, class Data> | 
|  | Data *LRUCache<Key, Data>::query(const Key &key) const | 
|  | { | 
|  | for(int i = top; i > top - fill; i--) | 
|  | { | 
|  | int j = i & mask; | 
|  |  | 
|  | if(key == *ref[j]) | 
|  | { | 
|  | Data *hit = data[j]; | 
|  |  | 
|  | if(i != top) | 
|  | { | 
|  | // Move one up | 
|  | int k = (j + 1) & mask; | 
|  |  | 
|  | Data *swapD = data[k]; | 
|  | data[k] = data[j]; | 
|  | data[j] = swapD; | 
|  |  | 
|  | Key *swapK = ref[k]; | 
|  | ref[k] = ref[j]; | 
|  | ref[j] = swapK; | 
|  | } | 
|  |  | 
|  | return hit; | 
|  | } | 
|  | } | 
|  |  | 
|  | return nullptr;   // Not found | 
|  | } | 
|  |  | 
|  | template<class Key, class Data> | 
|  | Data *LRUCache<Key, Data>::add(const Key &key, Data *data) | 
|  | { | 
|  | top = (top + 1) & mask; | 
|  | fill = fill + 1 < size ? fill + 1 : size; | 
|  |  | 
|  | *ref[top] = key; | 
|  |  | 
|  | data->bind(); | 
|  |  | 
|  | if(this->data[top]) | 
|  | { | 
|  | this->data[top]->unbind(); | 
|  | } | 
|  |  | 
|  | this->data[top] = data; | 
|  |  | 
|  | return data; | 
|  | } | 
|  | } | 
|  |  | 
|  | #endif   // sw_LRUCache_hpp |