class Rufus::Lru::Hash

A Hash that has a max size. After the maxsize has been reached, the least recently used entries (LRU hence), will be discared to make room for the new entries.

require 'rubygems'
require 'rufus/lru'

h = LruHash.new(3)

5.times { |i| h[i] = "a" * i }

puts h.inspect # >> {2=>"aa", 3=>"aaa", 4=>"aaaa"}

h[:newer] = "b"

puts h.inspect # >> {:newer=>"b", 3=>"aaa", 4=>"aaaa"}

One may want to squeeze hash manually

h = LruHash.new(3, true)
# or h.squeeze_on_demand=true after h is created
.
.
h.squeeze!

If a value has destructor method clear it may be called upon the key-value removal

h = LruHash.new(33, does_not_matter, true)
# or h.clear_value_on_removal=true after h is created

Nota bene: this class is not thread-safe. If you need something thread-safe, use Rufus::Lru::SynchronizedHash.

Attributes

lru_keys[R]
maxsize[R]
on_removal[RW]
ordered_keys[R]

Public Class Methods

new(maxsize, opts={}) click to toggle source

Initializes a LruHash with a given maxsize.

Options:

  • :auto_squeeze defaults to true

  • :on_removal accepts false, a symbol or a lambda.

    • False is the default, values are removed, nothing special happens.

    • A symbol can be used to point to a method like :clear or :destroy that has to be called on the value just removed

    • A lambda/proc can be set, it’s thus called (and passed the removed value as argument) each time a removal occurs

Calls superclass method
# File lib/rufus/lru.rb, line 89
def initialize(maxsize, opts={})

  fail ArgumentError.new("maxsize must be >= 0") if maxsize < 0

  super()

  @maxsize = maxsize
  @lru_keys = []

  @auto_squeeze = opts.has_key?(:auto_squeeze) ? opts[:auto_squeeze] : true
  @on_removal = opts[:on_removal]
end

Public Instance Methods

[](key) click to toggle source
Calls superclass method
# File lib/rufus/lru.rb, line 133
def [](key)

  return nil unless has_key?(key)

  touch(key)

  super
end
[]=(key, value) click to toggle source
Calls superclass method
# File lib/rufus/lru.rb, line 142
def []=(key, value)

  super
  touch(key)
  do_squeeze! if @auto_squeeze
end
auto_squeeze=(b) click to toggle source
# File lib/rufus/lru.rb, line 110
def auto_squeeze=(b)

  squeeze! if (@auto_squeeze = b)
end
auto_squeeze?() click to toggle source
# File lib/rufus/lru.rb, line 115
def auto_squeeze?

  @auto_squeeze
end
clear() click to toggle source
Calls superclass method
# File lib/rufus/lru.rb, line 120
def clear

  @lru_keys.clear

  self.each_value { |v| call_on_removal(v) }

  super
end
delete(key) click to toggle source
Calls superclass method
# File lib/rufus/lru.rb, line 156
def delete(key)

  value = super
  call_on_removal(value)

  @lru_keys.delete(key)

  value
end
maxsize=(i) click to toggle source
# File lib/rufus/lru.rb, line 102
def maxsize=(i)

  @maxsize = i
  squeeze! if @auto_squeeze

  i
end
merge!(hash) click to toggle source
# File lib/rufus/lru.rb, line 149
def merge!(hash)

  hash.each { |k, v| self[k] = v }

  # not using 'super', but in order not guaranteed at all...
end
squeeze!() click to toggle source
# File lib/rufus/lru.rb, line 173
def squeeze!; do_squeeze!; end
to_h() click to toggle source

Returns a regular Hash with the entries in this hash.

# File lib/rufus/lru.rb, line 168
def to_h

  {}.merge!(self)
end

Protected Instance Methods

call_on_removal(value) click to toggle source
# File lib/rufus/lru.rb, line 196
def call_on_removal(value)

  if ! @on_removal
    # nothing to do
  elsif @on_removal.is_a?(Symbol)
    value.send(@on_removal)
  else # must be a block
    @on_removal.call(value)
  end
end
do_squeeze!() click to toggle source

Makes sure that the hash fits its maxsize. If not, will remove the least recently used items.

# File lib/rufus/lru.rb, line 189
def do_squeeze!

  while size > @maxsize
    delete(@lru_keys.shift)
  end
end
touch(key) click to toggle source

Puts the key on top of the lru ‘stack’. The bottom being the lru place.

# File lib/rufus/lru.rb, line 180
def touch(key)

  @lru_keys.delete(key)
  @lru_keys << key
end