John Bauman | 8940182 | 2014-05-06 15:04:28 -0400 | [diff] [blame] | 1 | // SwiftShader Software Renderer
|
| 2 | //
|
| 3 | // Copyright(c) 2005-2011 TransGaming Inc.
|
| 4 | //
|
| 5 | // All rights reserved. No part of this software may be copied, distributed, transmitted,
|
| 6 | // transcribed, stored in a retrieval system, translated into any human or computer
|
| 7 | // language by any means, or disclosed to third parties without the explicit written
|
| 8 | // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
|
| 9 | // or implied, including but not limited to any patent rights, are granted to you.
|
| 10 | //
|
| 11 |
|
| 12 | #ifndef sw_LRUCache_hpp
|
| 13 | #define sw_LRUCache_hpp
|
| 14 |
|
| 15 | #include "Common/Math.hpp"
|
| 16 |
|
| 17 | namespace sw
|
| 18 | {
|
| 19 | template<class Key, class Data>
|
| 20 | class LRUCache
|
| 21 | {
|
| 22 | public:
|
| 23 | LRUCache(int n);
|
| 24 |
|
| 25 | ~LRUCache();
|
| 26 |
|
| 27 | Data *query(const Key &key) const;
|
| 28 | Data *add(const Key &key, Data *data);
|
| 29 |
|
| 30 | int getSize() {return size;}
|
| 31 | Key &getKey(int i) {return key[i];}
|
| 32 |
|
| 33 | private:
|
| 34 | int size;
|
| 35 | int mask;
|
| 36 | int top;
|
| 37 | int fill;
|
| 38 |
|
| 39 | Key *key;
|
| 40 | Key **ref;
|
| 41 | Data **data;
|
| 42 | };
|
| 43 | }
|
| 44 |
|
| 45 | namespace sw
|
| 46 | {
|
| 47 | template<class Key, class Data>
|
| 48 | LRUCache<Key, Data>::LRUCache(int n)
|
| 49 | {
|
| 50 | size = ceilPow2(n);
|
| 51 | mask = size - 1;
|
| 52 | top = 0;
|
| 53 | fill = 0;
|
| 54 |
|
| 55 | key = new Key[size];
|
| 56 | ref = new Key*[size];
|
| 57 | data = new Data*[size];
|
| 58 |
|
| 59 | for(int i = 0; i < size; i++)
|
| 60 | {
|
| 61 | data[i] = 0;
|
| 62 |
|
| 63 | ref[i] = &key[i];
|
| 64 | }
|
| 65 | }
|
| 66 |
|
| 67 | template<class Key, class Data>
|
| 68 | LRUCache<Key, Data>::~LRUCache()
|
| 69 | {
|
| 70 | delete[] key;
|
| 71 | key = 0;
|
| 72 |
|
| 73 | delete[] ref;
|
| 74 | ref = 0;
|
| 75 |
|
| 76 | for(int i = 0; i < size; i++)
|
| 77 | {
|
| 78 | if(data[i])
|
| 79 | {
|
| 80 | data[i]->unbind();
|
| 81 | data[i] = 0;
|
| 82 | }
|
| 83 | }
|
| 84 |
|
| 85 | delete[] data;
|
| 86 | data = 0;
|
| 87 | }
|
| 88 |
|
| 89 | template<class Key, class Data>
|
| 90 | Data *LRUCache<Key, Data>::query(const Key &key) const
|
| 91 | {
|
| 92 | for(int i = top; i > top - fill; i--)
|
| 93 | {
|
| 94 | int j = i & mask;
|
| 95 |
|
| 96 | if(key == *ref[j])
|
| 97 | {
|
| 98 | Data *hit = data[j];
|
| 99 |
|
| 100 | if(i != top)
|
| 101 | {
|
| 102 | // Move one up
|
| 103 | int k = (j + 1) & mask;
|
| 104 |
|
| 105 | Data *swapD = data[k];
|
| 106 | data[k] = data[j];
|
| 107 | data[j] = swapD;
|
| 108 |
|
| 109 | Key *swapK = ref[k];
|
| 110 | ref[k] = ref[j];
|
| 111 | ref[j] = swapK;
|
| 112 | }
|
| 113 |
|
| 114 | return hit;
|
| 115 | }
|
| 116 | }
|
| 117 |
|
| 118 | return 0; // Not found
|
| 119 | }
|
| 120 |
|
| 121 | template<class Key, class Data>
|
| 122 | Data *LRUCache<Key, Data>::add(const Key &key, Data *data)
|
| 123 | {
|
| 124 | top = (top + 1) & mask;
|
| 125 | fill = fill + 1 < size ? fill + 1 : size;
|
| 126 |
|
| 127 | *ref[top] = key;
|
| 128 |
|
| 129 | data->bind();
|
| 130 |
|
| 131 | if(this->data[top])
|
| 132 | {
|
| 133 | this->data[top]->unbind();
|
| 134 | }
|
| 135 |
|
| 136 | this->data[top] = data;
|
| 137 |
|
| 138 | return data;
|
| 139 | }
|
| 140 | }
|
| 141 |
|
| 142 | #endif // sw_LRUCache_hpp
|