Module: When::Parts::MethodCash
- Included in:
- Coordinates::Temporal, Ephemeris::Formula
- Defined in:
- lib/when_exe/parts/method_cash.rb
Overview
メソッドの実行結果をキャッシュし処理の高速化を行う
fn というメソッドをキャッシュ化
* fn ではなく fn_ を定義しておく
* fn メソッドが呼ばれると fn_ を実行し、{引数=>戻り値} を Hash に記憶する
* 同じ引数で再度 fn メソッドが呼ばれると Hash から戻り値を取り出して返す
a_to_b と b_to_a という互いに逆関数のメソッドをキャッシュ化
* a_to_b ではなく a_to_b_ , b_to_a ではなく b_to_a_ を定義しておく
* a_to_b メソッドが呼ばれると a_to_b_ を実行し、{引数=>戻り値}, {戻り値=>引数}を Hash に記憶する
* 同じ引数で再度 a_to_b メソッドが呼ばれると Hash から戻り値を取り出して返す
* b_to_a メソッドが呼ばれ Hash に戻り値があれば Hash から戻り値を取り出して返す
特記事項
Argument identification
The eql? method of When::TM::(Temporal)Position is not overridden.
It seems that the cost of identification of the argument exceeds the merit of the method cash.
I do not recommend applying the methodcash to the method which takes
When::TM::(Temporal)Position as an argument.
Multi-thread critical situation
There is a problem in consistency of hash when this function is used in multi-thread environment.
If the initialize method sets Mutex in instance variable @_m_cash_lock_,
this function gives up use of hash in the critical situation.
class Foo
include MethodCash
def initialize
...
@_m_cash_lock_ = Mutex.new
...
end
end
参考 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/47663
Instance Method Summary collapse
-
#method_missing(name, *args, &block) ⇒ void
最初に発生する method_missing で、キャッシュ機能を登録する.
- #method_missing_ ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ void
This method returns an undefined value.
最初に発生する method_missing で、キャッシュ機能を登録する
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/when_exe/parts/method_cash.rb', line 65 def method_missing(name, *args, &block) return method_missing_(name, *args, &block) unless respond_to?("#{name}_", true) if ((name.to_s =~ /^(_*)(.+?)_to_(.+)$/) && respond_to?("#{$1}#{$3}_to_#{$2}_", true)) prefix, from, to = $~[1..3] begin if (@_m_cash_lock_) return send("#{prefix}#{from}_to_#{to}_", *args, &block) unless @_m_cash_lock_.try_lock unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock" end [[from, to],[to, from]].each do |pair| a, b = pair lock = @_m_cash_lock_ ? " return #{prefix}#{a}_to_#{b}_(*args) unless @_m_cash_lock_.try_lock" : '' instance_eval %Q{ def #{prefix}#{a}_to_#{b}(*args) key = _key_simplefy(args) inv = @_m_cash_["#{prefix}#{a}_to_#{b}"][key] return inv if inv begin #{lock} inv = #{prefix}#{a}_to_#{b}_(*args) @_m_cash_["#{prefix}#{b}_to_#{a}"][_key_simplefy(inv)] = args @_m_cash_["#{prefix}#{a}_to_#{b}"][key] = inv return inv #{unlock} end end } end key = _key_simplefy(args) inv = send("#{prefix}#{from}_to_#{to}_", *args) @_m_cash_ ||= {} @_m_cash_["#{prefix}#{to}_to_#{from}"] ||= {} @_m_cash_["#{prefix}#{from}_to_#{to}"] ||= {} @_m_cash_["#{prefix}#{to}_to_#{from}"][_key_simplefy(inv)] = args @_m_cash_["#{prefix}#{from}_to_#{to}"][key] = inv return inv ensure @_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock end else begin respond = respond_to?("#{name}_setup", true) setup = respond ? "#{name}_setup(key, *args)" : "(@_m_cash_[\"#{name}\"][key] = #{name}_(*args))" if (@_m_cash_lock_) return send("#{name}_", *args, &block) unless @_m_cash_lock_.try_lock lock = " return #{name}_(*args) unless @_m_cash_lock_.try_lock" unlock = "ensure ; @_m_cash_lock_.locked? && @_m_cash_lock_.unlock" end instance_eval %Q{ def #{name}(*args) key = _key_simplefy(args) ret = @_m_cash_["#{name}"][key] return ret if ret begin #{lock} return #{setup} #{unlock} end end } key = _key_simplefy(args) @_m_cash_ ||= {} @_m_cash_["#{name}"] ||= {} if (respond) return send("#{name}_setup", key, *args) else return(@_m_cash_["#{name}"][key] ||= send("#{name}_", *args)) end ensure @_m_cash_lock_ && @_m_cash_lock_.locked? && @_m_cash_lock_.unlock end end end |
Instance Method Details
#method_missing_ ⇒ Object
54 |
# File 'lib/when_exe/parts/method_cash.rb', line 54 alias :method_missing_ :method_missing |