lru_redux 0.8.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44f9731a90a6a4021eec3488c38c5a82399f7089
4
- data.tar.gz: cd4f27cc1d9eca928e1a1e8c9b75507a4c06a81d
3
+ metadata.gz: ee0116ff3d2b67bcd4afa09cc37dff5d64d1f173
4
+ data.tar.gz: 1a8db0cbbecb94b2f112ef2482f7a76f2335dd03
5
5
  SHA512:
6
- metadata.gz: e5b6832027fc7e09a7e319981ef2acc9399b11fdce5015c7c24354f6e50dbc8794b056cc995733387dbc9b658e67bc610b92a55dc905905f53b7d8e1f8a50398
7
- data.tar.gz: ac925de76a377ffd499c20c626f4eb650232b4deb888cd7958452a24c425ce0a64fe6a8e62373d6c8e8e2a1bc3bd0f14f4aeb54475fb70edb1cf6bea2ae061a4
6
+ metadata.gz: 1982913819cd75633cef5158c3adc14d0680a3a5fd1c4c4bec4a5f73455817c76d4f7a65e0ffc3fd9ef2b03c73db4948c39464585439c6867e5850c5a1f080e9
7
+ data.tar.gz: 3da4da91b505b90a9ce57fc0f1abc288aee7cc1496e16e020e234dfa621c1b1cd179fed22d467addeb2fedcbc7acdbc1d797c8e072549f405a8016ec1c78cdc1
data/README.md CHANGED
@@ -1,10 +1,14 @@
1
- # LruRedux
2
-
3
- An efficient thread safe lru cache.
4
-
5
- Lru Redux uses a Hash/Double link list backed storage to keep track of nodes in a cache based on last usage.
6
-
7
- This provides a correct and well specified LRU cache, that is very efficient. Additionally you can optionally use a thread safe wrapper.
1
+ # LruRedux [![Gem Version](https://badge.fury.io/rb/lru_redux.svg)](http://badge.fury.io/rb/lru_redux)
2
+ An efficient, thread safe LRU cache.
3
+
4
+ - [Installation](#installation)
5
+ - [Usage](#usage)
6
+ - [TTL Cache](#ttl-cache)
7
+ - [Cache Methods](#cache-methods)
8
+ - [Benchmarks](#benchmarks)
9
+ - [Other Caches](#other-caches)
10
+ - [Contributing](#contributing)
11
+ - [Changelog](#changelog)
8
12
 
9
13
  ## Installation
10
14
 
@@ -20,6 +24,10 @@ Or install it yourself as:
20
24
 
21
25
  $ gem install lru_redux
22
26
 
27
+ Ruby 1.8 - v0.8.4 is the last compatible release:
28
+
29
+ gem 'lru_redux', '~> 0.8.4'
30
+
23
31
  ## Usage
24
32
 
25
33
  ```ruby
@@ -61,29 +69,174 @@ cache = LruRedux::ThreadSafeCache.new(100)
61
69
 
62
70
  ```
63
71
 
72
+ #### TTL Cache
73
+ The TTL cache extends the functionality of the LRU cache with a Time To Live eviction strategy. TTL eviction occurs on every access and takes precedence over LRU eviction, meaning a 'live' value will never be evicted over an expired one.
74
+
75
+ ```ruby
76
+ # Timecop is gem that allows us to change Time.now
77
+ # and is used for demonstration purposes.
78
+ require 'lru_redux'
79
+ require 'timecop'
80
+
81
+ # Create a TTL cache with a size of 100 and TTL of 5 minutes.
82
+ # The first argument is the size and
83
+ # the second optional argument is the TTL in seconds.
84
+ cache = LruRedux::TTL::Cache.new(100, 5 * 60)
85
+
86
+ Timecop.freeze(Time.now)
87
+
88
+ cache[:a] = "1"
89
+ cache[:b] = "2"
90
+
91
+ cache.to_a
92
+ # => [[:b,"2"],[:a,"1"]]
93
+
94
+ # Now we advance time 5 min 30 sec into the future.
95
+ Timecop.freeze(Time.now + 330)
96
+
97
+ # And we see that the expired values have been evicted.
98
+ cache.to_a
99
+ # => []
100
+
101
+ # The TTL can be updated on a live cache using #ttl=.
102
+ # Currently cached items will be evicted under the new TTL.
103
+ cache[:a] = "1"
104
+ cache[:b] = "2"
105
+
106
+ Timecop.freeze(Time.now + 330)
107
+
108
+ cache.ttl = 10 * 60
109
+
110
+ # Since ttl eviction is triggered by access,
111
+ # the items are still cached when the ttl is changed and
112
+ # are now under the 10 minute TTL.
113
+ cache.to_a
114
+ # => [[:b,"2"],[:a,"1"]]
115
+
116
+ # TTL eviction can be triggered manually with the #expire method.
117
+ Timecop.freeze(Time.now + 330)
118
+
119
+ cache.expire
120
+ cache.to_a
121
+ # => []
122
+
123
+ Timecop.return
124
+
125
+ # The behavior of a TTL cache with the TTL set to `:none`
126
+ # is identical to the LRU cache.
127
+
128
+ cache = LruRedux::TTL::Cache.new(100, :none)
129
+
130
+ # The TTL argument is optional and defaults to `:none`.
131
+ cache = LruRedux::TTL::Cache.new(100)
132
+
133
+ # A thread safe version is available.
134
+ cache = LruRedux::TTL::ThreadSafeCache.new(100, 5 * 60)
135
+ ```
136
+
137
+ ## Cache Methods
138
+ - `#getset` Takes a key and block. Will return a value if cached, otherwise will execute the block and cache the resulting value.
139
+ - `#fetch` Takes a key and optional block. Will return a value if cached, otherwise will execute the block and return the resulting value or return nil if no block is provided.
140
+ - `#[]` Takes a key. Will return a value if cached, otherwise nil.
141
+ - `#[]=` Takes a key and value. Will cache the value under the key.
142
+ - `#delete` Takes a key. Will return the deleted value, otherwise nil.
143
+ - `#evict` Alias for `#delete`.
144
+ - `#clear` Clears the cache. Returns nil.
145
+ - `#each` Takes a block. Executes the block on each key-value pair in LRU order (most recent first).
146
+ - `#to_a` Return an array of key-value pairs (arrays) in LRU order (most recent first).
147
+ - `#key?` Takes a key. Returns true if the key is cached, otherwise false.
148
+ - `#has_key?` Alias for `#key?`.
149
+ - `#count` Return the current number of items stored in the cache.
150
+ - `#max_size` Returns the current maximum size of the cache.
151
+ - `#max_size=` Takes a positive number. Changes the current max_size and triggers a resize. Also triggers TTL eviction on the TTL cache.
152
+
153
+ #### TTL Cache Specific
154
+ - `#ttl` Returns the current TTL of the cache.
155
+ - `#ttl=` Takes `:none` or a positive number. Changes the current ttl and triggers a TTL eviction.
156
+ - `#expire` Triggers a TTL eviction.
157
+
64
158
  ## Benchmarks
65
159
 
66
160
  see: benchmark directory (a million random lookup / store)
67
161
 
162
+ #### LRU
163
+ ##### Ruby 2.2.1
68
164
  ```
69
165
  $ ruby ./bench/bench.rb
70
- Rehearsal ---------------------------------------------------------
71
- thread safe lru 4.530000 0.020000 4.550000 ( 4.540861)
72
- lru gem 2.040000 0.000000 2.040000 ( 2.046777)
73
- lru_cache gem 1.660000 0.010000 1.670000 ( 1.670404)
74
- lru_redux gem 1.200000 0.000000 1.200000 ( 1.197036)
75
- lru_redux thread safe 2.520000 0.000000 2.520000 ( 2.526945)
76
- ----------------------------------------------- total: 11.980000sec
77
-
78
- user system total real
79
- thread safe lru 4.550000 0.030000 4.580000 ( 4.581848)
80
- lru gem 2.060000 0.000000 2.060000 ( 2.056636)
81
- lru_cache gem 1.660000 0.010000 1.670000 ( 1.669312)
82
- lru_redux gem 1.180000 0.000000 1.180000 ( 1.187639)
83
- lru_redux thread safe 2.530000 0.000000 2.530000 ( 2.532061)
84
166
 
167
+ Rehearsal -------------------------------------------------------------
168
+ ThreadSafeLru 4.500000 0.030000 4.530000 ( 4.524213)
169
+ LRU 2.250000 0.000000 2.250000 ( 2.249670)
170
+ LRUCache 1.720000 0.010000 1.730000 ( 1.728243)
171
+ LruRedux::Cache 0.960000 0.000000 0.960000 ( 0.961292)
172
+ LruRedux::ThreadSafeCache 2.180000 0.000000 2.180000 ( 2.187714)
173
+ --------------------------------------------------- total: 11.650000sec
174
+
175
+ user system total real
176
+ ThreadSafeLru 4.390000 0.020000 4.410000 ( 4.415703)
177
+ LRU 2.140000 0.010000 2.150000 ( 2.149626)
178
+ LRUCache 1.680000 0.010000 1.690000 ( 1.688564)
179
+ LruRedux::Cache 0.910000 0.000000 0.910000 ( 0.913108)
180
+ LruRedux::ThreadSafeCache 2.200000 0.010000 2.210000 ( 2.212108)
85
181
  ```
86
182
 
183
+ ##### Ruby 2.0.0-p643
184
+ Implementation is slightly different for Ruby versions before 2.1 due to a Ruby bug. http://bugs.ruby-lang.org/issues/8312
185
+ ```
186
+ $ ruby ./bench/bench.rb
187
+ Rehearsal -------------------------------------------------------------
188
+ ThreadSafeLru 4.790000 0.040000 4.830000 ( 4.828370)
189
+ LRU 2.170000 0.010000 2.180000 ( 2.180630)
190
+ LRUCache 1.810000 0.000000 1.810000 ( 1.814737)
191
+ LruRedux::Cache 1.330000 0.010000 1.340000 ( 1.325554)
192
+ LruRedux::ThreadSafeCache 2.770000 0.000000 2.770000 ( 2.777754)
193
+ --------------------------------------------------- total: 12.930000sec
194
+
195
+ user system total real
196
+ ThreadSafeLru 4.710000 0.060000 4.770000 ( 4.773233)
197
+ LRU 2.120000 0.010000 2.130000 ( 2.135111)
198
+ LRUCache 1.780000 0.000000 1.780000 ( 1.781392)
199
+ LruRedux::Cache 1.190000 0.010000 1.200000 ( 1.201908)
200
+ LruRedux::ThreadSafeCache 2.650000 0.010000 2.660000 ( 2.652580)
201
+ ```
202
+
203
+ #### TTL
204
+ ##### Ruby 2.2.1
205
+ ```
206
+ $ ruby ./bench/bench_ttl.rb
207
+ Rehearsal -----------------------------------------------------------------------
208
+ FastCache 6.240000 0.070000 6.310000 ( 6.302569)
209
+ LruRedux::TTL::Cache 4.700000 0.010000 4.710000 ( 4.712858)
210
+ LruRedux::TTL::ThreadSafeCache 6.300000 0.010000 6.310000 ( 6.319032)
211
+ LruRedux::TTL::Cache (TTL disabled) 2.460000 0.010000 2.470000 ( 2.470629)
212
+ ------------------------------------------------------------- total: 19.800000sec
213
+
214
+ user system total real
215
+ FastCache 6.470000 0.070000 6.540000 ( 6.536193)
216
+ LruRedux::TTL::Cache 4.640000 0.010000 4.650000 ( 4.661793)
217
+ LruRedux::TTL::ThreadSafeCache 6.310000 0.020000 6.330000 ( 6.328840)
218
+ LruRedux::TTL::Cache (TTL disabled) 2.440000 0.000000 2.440000 ( 2.446269)
219
+ ```
220
+
221
+ ## Other Caches
222
+ This is a list of the caches that are used in the benchmarks.
223
+
224
+ #### LRU
225
+ - RubyGems: https://rubygems.org/gems/lru
226
+ - Homepage: http://lru.rubyforge.org/
227
+
228
+ #### LRUCache
229
+ - RubyGems: https://rubygems.org/gems/lru_cache
230
+ - Homepage: https://github.com/brendan/lru_cache
231
+
232
+ #### ThreadSafeLru
233
+ - RubyGems: https://rubygems.org/gems/threadsafe-lru
234
+ - Homepage: https://github.com/draganm/threadsafe-lru
235
+
236
+ #### FastCache
237
+ - RubyGems: https://rubygems.org/gems/fast_cache
238
+ - Homepage: https://github.com/swoop-inc/fast_cache
239
+
87
240
 
88
241
  ## Contributing
89
242
 
@@ -94,20 +247,28 @@ lru_redux thread safe 2.530000 0.000000 2.530000 ( 2.532061)
94
247
  5. Create new Pull Request
95
248
 
96
249
  ## Changlog
250
+ ###version 1.1.0 - 30-Mar-2015
251
+
252
+ - New: TTL cache added. This cache is LRU like with the addition of time-based eviction. Check the Usage -> TTL Cache section in README.md for details.
253
+
254
+ ###version 1.0.0 - 26-Mar-2015
255
+
256
+ - Ruby Support: Ruby 1.9+ is now required by LruRedux. If you need to use LruRedux in Ruby 1.8, please specify gem version 0.8.4 in your Gemfile. v0.8.4 is the last 1.8 compatible release and included a number of fixes and performance improvements for the Ruby 1.8 implementation. @Seberius
257
+ - Perf: improve performance in Ruby 2.1+ on the MRI @Seberius
97
258
 
98
- ###version 0.8.4 - 20-Feb-2014
259
+ ###version 0.8.4 - 20-Feb-2015
99
260
 
100
- - Fix: regression of ThreadSafeCache under JRuby 1.7 @Sevrius
261
+ - Fix: regression of ThreadSafeCache under JRuby 1.7 @Seberius
101
262
 
102
- ###version 0.8.3 - 20-Feb-2014
263
+ ###version 0.8.3 - 20-Feb-2015
103
264
 
104
- - Perf: improve ThreadSafeCache performance @Sevrius
265
+ - Perf: improve ThreadSafeCache performance @Seberius
105
266
 
106
- ###version 0.8.2 - 16-Feb-2014
267
+ ###version 0.8.2 - 16-Feb-2015
107
268
 
108
- - Perf: use #size instead of #count when checking length @Sebrius
109
- - Fix: Cache could grow beyond its size in Ruby 1.8 @Sebrius
110
- - Fix: #each could deadlock in Ruby 1.8 @Sebrius
269
+ - Perf: use #size instead of #count when checking length @Seberius
270
+ - Fix: Cache could grow beyond its size in Ruby 1.8 @Seberius
271
+ - Fix: #each could deadlock in Ruby 1.8 @Seberius
111
272
 
112
273
 
113
274
  ###version 0.8.1 - 7-Sep-2013
data/Rakefile CHANGED
@@ -3,5 +3,5 @@ require "bundler/gem_tasks"
3
3
  require 'rake/testtask'
4
4
 
5
5
  Rake::TestTask.new do |t|
6
- t.pattern = "test/*_test.rb"
6
+ t.pattern = "test/**/*_test.rb"
7
7
  end
@@ -1,45 +1,43 @@
1
- require 'rubygems'
2
- require 'lru'
1
+ require 'bundler'
3
2
  require 'benchmark'
3
+ require 'lru'
4
4
  require 'lru_cache'
5
5
  require 'threadsafe-lru'
6
- $LOAD_PATH.unshift File.expand_path '../lib'
7
- require File.expand_path('../../lib/lru_redux', __FILE__)
8
6
 
7
+ Bundler.require
8
+
9
+ # Lru
9
10
  lru = Cache::LRU.new(max_elements: 1_000)
11
+
12
+ # LruCache
10
13
  lru_cache = LRUCache.new(1_000)
11
14
 
12
- lru_redux = LruRedux::Cache.new(1_000)
13
- lru_redux_thread_safe = LruRedux::ThreadSafeCache.new(1_000)
15
+ # ThreadSafeLru
14
16
  thread_safe_lru = ThreadSafeLru::LruCache.new(1_000)
15
17
 
16
- bm = Benchmark.bmbm do |bm|
18
+ # LruRedux
19
+ redux = LruRedux::Cache.new(1_000)
20
+ redux_thread_safe = LruRedux::ThreadSafeCache.new(1_000)
21
+
22
+ puts "** LRU Benchmarks **"
23
+ Benchmark.bmbm do |bm|
24
+ bm.report 'ThreadSafeLru' do
25
+ 1_000_000.times { thread_safe_lru.get(rand(2_000)) { :value } }
26
+ end
27
+
28
+ bm.report 'LRU' do
29
+ 1_000_000.times { lru[rand(2_000)] ||= :value }
30
+ end
17
31
 
18
- bm.report "thread safe lru" do
19
- 1_000_000.times do
20
- thread_safe_lru.get(rand(2_000)){ :value }
21
- end
32
+ bm.report 'LRUCache' do
33
+ 1_000_000.times { lru_cache[rand(2_000)] ||= :value }
22
34
  end
23
35
 
24
- [
25
- [lru, "lru gem"],
26
- [lru_cache, "lru_cache gem"],
27
- ].each do |cache, name|
28
- bm.report name do
29
- 1_000_000.times do
30
- cache[rand(2_000)] ||= :value
31
- end
32
- end
36
+ bm.report 'LruRedux::Cache' do
37
+ 1_000_000.times { redux.getset(rand(2_000)) { :value } }
33
38
  end
34
39
 
35
- [
36
- [lru_redux, "lru_redux gem"],
37
- [lru_redux_thread_safe, "lru_redux thread safe"]
38
- ].each do |cache, name|
39
- bm.report name do
40
- 1_000_000.times do
41
- cache.getset(rand(2_000)) { :value }
42
- end
43
- end
40
+ bm.report 'LruRedux::ThreadSafeCache' do
41
+ 1_000_000.times { redux_thread_safe.getset(rand(2_000)) { :value } }
44
42
  end
45
43
  end
@@ -0,0 +1,33 @@
1
+ require 'bundler'
2
+ require 'benchmark'
3
+ require 'fast_cache'
4
+
5
+ Bundler.require
6
+
7
+ # FastCache
8
+ fast_cache = FastCache::Cache.new(1_000, 5 * 60)
9
+
10
+ # LruRedux
11
+ redux_ttl = LruRedux::TTL::Cache.new(1_000, 5 * 60)
12
+ redux_ttl_thread_safe = LruRedux::TTL::ThreadSafeCache.new(1_000, 5 * 60)
13
+ redux_ttl_disabled = LruRedux::TTL::Cache.new(1_000, :none)
14
+
15
+ puts
16
+ puts "** TTL Benchmarks **"
17
+ Benchmark.bmbm do |bm|
18
+ bm.report 'FastCache' do
19
+ 1_000_000.times { fast_cache.fetch(rand(2_000)) { :value } }
20
+ end
21
+
22
+ bm.report 'LruRedux::TTL::Cache' do
23
+ 1_000_000.times { redux_ttl.getset(rand(2_000)) { :value } }
24
+ end
25
+
26
+ bm.report 'LruRedux::TTL::ThreadSafeCache' do
27
+ 1_000_000.times { redux_ttl_thread_safe.getset(rand(2_000)) { :value } }
28
+ end
29
+
30
+ bm.report 'LruRedux::TTL::Cache (TTL disabled)' do
31
+ 1_000_000.times { redux_ttl_disabled.getset(rand(2_000)) { :value } }
32
+ end
33
+ end
@@ -1,16 +1,11 @@
1
- module LruRedux
2
- def self.is_19?
3
- major,minor = RUBY_VERSION.split(".").map{|a| a.to_i}
4
- major > 1 || (major == 1 && minor > 8)
5
- end
6
- end
1
+ require "lru_redux/util"
2
+
3
+ require "lru_redux/cache"
4
+ require "lru_redux/cache_legacy" if
5
+ RUBY_ENGINE == "ruby" && RUBY_VERSION < "2.1.0"
7
6
 
8
- require "lru_redux/version"
9
- if LruRedux.is_19?
10
- require "lru_redux/cache19"
11
- else
12
- require "lru_redux/cache"
13
- end
14
7
  require "lru_redux/thread_safe_cache"
15
- require "lru_redux/thread_safe_cache_jruby" if
16
- RUBY_PLATFORM == 'java' && JRUBY_VERSION < '9.0'
8
+
9
+ require "lru_redux/ttl"
10
+
11
+ require "lru_redux/version"
@@ -1,163 +1,108 @@
1
-
2
-
1
+ # Ruby 1.9 makes our life easier, Hash is already ordered
2
+ #
3
+ # This is an ultra efficient 1.9 freindly implementation
3
4
  class LruRedux::Cache
5
+ def initialize(*args)
6
+ max_size, _ = args
4
7
 
5
- # for high efficiency nodes in double linked list are stored in arrays
6
- # [prev,key,val,next]
7
- #
8
- # This makes this much more annoying to code, but gives us a 5-10% edge
8
+ raise ArgumentError.new(:max_size) if max_size < 1
9
9
 
10
- def initialize(max_size)
11
10
  @max_size = max_size
12
11
  @data = {}
13
- @head = nil
14
- @tail = nil
15
12
  end
16
13
 
17
- def max_size=(size)
18
- raise ArgumentError.new(:max_size) if @max_size < 1
19
- @max_size = size
20
- while pop_tail
21
- # no op
22
- end
14
+ def max_size=(max_size)
15
+ max_size ||= @max_size
16
+
17
+ raise ArgumentError.new(:max_size) if max_size < 1
18
+
19
+ @max_size = max_size
20
+
21
+ @data.shift while @data.size > @max_size
22
+ end
23
+
24
+ def ttl=(_)
25
+ nil
23
26
  end
24
27
 
25
28
  def getset(key)
26
- node = @data[key]
27
- if node
28
- move_to_head(node)
29
- node[2]
29
+ found = true
30
+ value = @data.delete(key){ found = false }
31
+ if found
32
+ @data[key] = value
30
33
  else
31
- self[key] = yield
34
+ result = @data[key] = yield
35
+ @data.shift if @data.length > @max_size
36
+ result
32
37
  end
33
38
  end
34
39
 
35
40
  def fetch(key)
36
- node = @data[key]
37
- if node
38
- move_to_head(node)
39
- node[2]
41
+ found = true
42
+ value = @data.delete(key){ found = false }
43
+ if found
44
+ @data[key] = value
40
45
  else
41
46
  yield if block_given?
42
47
  end
43
48
  end
44
49
 
45
50
  def [](key)
46
- node = @data[key]
47
- if node
48
- move_to_head(node)
49
- node[2]
51
+ found = true
52
+ value = @data.delete(key){ found = false }
53
+ if found
54
+ @data[key] = value
55
+ else
56
+ nil
50
57
  end
51
58
  end
52
59
 
53
60
  def []=(key,val)
54
- node = @data[key]
55
- if node
56
- move_to_head(node)
57
- node[2] = val
58
- else
59
- @data[key] = add_to_head(key,val)
60
- pop_tail
61
- end
61
+ @data.delete(key)
62
+ @data[key] = val
63
+ @data.shift if @data.length > @max_size
62
64
  val
63
65
  end
64
66
 
65
67
  def each
66
- a = to_a
67
- a.each do |pair|
68
+ array = @data.to_a
69
+ array.reverse!.each do |pair|
68
70
  yield pair
69
71
  end
70
72
  end
71
73
 
72
- def each_unsafe
73
- n = @head
74
- if n
75
- while n
76
- yield [n[1], n[2]]
77
- n = n[0]
78
- end
79
- end
80
- end
74
+ # used further up the chain, non thread safe each
75
+ alias_method :each_unsafe, :each
81
76
 
82
77
  def to_a
83
- a = []
84
- self.each_unsafe do |k,v|
85
- a << [k,v]
86
- end
87
- a
78
+ array = @data.to_a
79
+ array.reverse!
88
80
  end
89
81
 
90
82
  def delete(key)
91
- node = @data.delete(key)
92
-
93
- return unless node
94
-
95
- prev = node[0]
96
- nex = node[3]
83
+ @data.delete(key)
84
+ end
97
85
 
98
- nex ? nex[0] = prev : @head = prev
99
- prev ? prev[3] = nex : @tail = nex
86
+ alias_method :evict, :delete
100
87
 
101
- node[2]
88
+ def key?(key)
89
+ @data.key?(key)
102
90
  end
103
91
 
92
+ alias_method :has_key?, :key?
93
+
104
94
  def clear
105
95
  @data.clear
106
- @head = @tail = nil
107
96
  end
108
97
 
109
98
  def count
110
99
  @data.size
111
100
  end
112
101
 
113
- # for cache validation only, ensures all is sound
114
- def valid?
115
- count = 0
116
- self.each_unsafe do |k,v|
117
- return false if @data[k][2] != v
118
- count += 1
119
- end
120
- count == @data.size
121
- end
122
-
123
102
  protected
124
103
 
125
- def add_to_head(key,val)
126
- if @head.nil?
127
- @tail = @head = [nil,key,val,nil]
128
- else
129
- node = [@head,key,val,nil]
130
- @head = @head[3] = node
131
- end
132
- end
133
-
134
- def move_to_head(node)
135
- return unless @head && node[1] != @head[1]
136
-
137
- prev = node[0]
138
- nex = node[3]
139
-
140
- if prev
141
- prev[3] = nex
142
- else
143
- @tail = nex
144
- end
145
-
146
- if nex
147
- nex[0] = prev
148
- end
149
-
150
- @head[3] = node
151
- node[0] = @head
152
- @head = node
153
- end
154
-
155
- def pop_tail
156
- if @data.length > @max_size
157
- @data.delete(@tail[1])
158
- @tail = @tail[3]
159
- @tail[0] = nil
160
- true
161
- end
104
+ # for cache validation only, ensures all is sound
105
+ def valid?
106
+ true
162
107
  end
163
108
  end