Class: Appear::Util::Memoizer

Inherits:
Object
  • Object
show all
Defined in:
lib/appear/util/memoizer.rb

Overview

A Memoizer memoizes calls to a block, skipping repeated work when the arguments are the same. Memoization is thread-safe, so it’s safe to memoize pure computations that occur on different threads.

Examples:

memoize a method

class Example
  def initialize
    @memo = Memoizer.new
  end

  def foo(a, b)
    @memo.call(a, b) do
      expensive_computaion(a, b)
    end
  end
end

memoize part of a computation

class Example
  def initialize
    @memo = Memoizer.new
  end

  def foo(a, b)
    state = get_state(a, b)
    d = memo.call(state) { expensive_pure_computation(state) }
    [a, d]
  end
end

Instance Method Summary collapse

Constructor Details

#initializeMemoizer

Returns a new instance of Memoizer.



35
36
37
38
39
# File 'lib/appear/util/memoizer.rb', line 35

def initialize
  @cache = {}
  @cache_mutex = Mutex.new
  @disable = false
end

Instance Method Details

#call(*args) ⇒ Any

Memoize the call to a block. Any arguments given to this method will be passed to the given block.

Parameters:

  • args (Array<Any>)

    memoization key

Returns:

  • (Any)

    result of the block

Raises:

  • (ArgumentError)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/appear/util/memoizer.rb', line 46

def call(*args)
  raise ArgumentError.new('no block given') unless block_given?

  if @disable
    return yield
  end

  @cache_mutex.synchronize do
    return @cache[args] if @cache.key?(args)
  end

  result = yield
  @cache_mutex.synchronize do
    @cache[args] = result
  end
  result
end

#clear!self

Evict the cache

Returns:

  • (self)


67
68
69
70
71
72
# File 'lib/appear/util/memoizer.rb', line 67

def clear!
  @cache_mutex.synchronize do
    @cache = {}
  end
  self
end

#disable!self

Disable memoization permanently on this instance.

Returns:

  • (self)


77
78
79
80
# File 'lib/appear/util/memoizer.rb', line 77

def disable!
  @disable = true
  self
end