lru_redux 0.8.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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