読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

インスタンスの所有者を探索するクラス

任意のインスタンスの所有者(インスタンス変数としてインスタンスを保持するインスタンス)を探索するクラスを書いてみました。

  1. ObjectSpaceを使ってインスタンスを列挙して、全ての所有インスタンスのIDを記録。
  2. 記録したデータを元に、逆引きで所有者の一覧を得る。

という仕組みです。クラス変数とかグローバル変数、ローカル変数で所有されているものはスルーしてます。

# インスタンスの所有者を探す。
class Owners
  def collect
    @owners = {}
    ObjectSpace.each_object {|object|
      id = object.object_id
      object.instance_variables.each {|n|
        v = object.instance_variable_get( n )
        @owners[v.object_id] ||= []
        @owners[v.object_id] << id
      }
    }
  end
  def owners( obj )
    (@owners[obj.object_id] || []).map {|id|
        o = ObjectSpace._id2ref(id)
        "#{o.object_id} : #{o.class.to_s}"
    }
  end
end

呼び出し例。

# テスト用クラス
class A
  def initialize( obj )
    @obj = obj
  end
end
class B
  def initialize( obj )
    @obj = obj
  end  
end
class C; end

#簡単な所有関係を形成
c = C.new
b = B.new(c)
a = A.new(b)
a2 = A.new(c)

#探索クラス
owners = Owners.new
owners.collect # 現在の所有関係を記録

#所有者を探索
p owners.owners( c )
p owners.owners( b )
p owners.owners( a )
p owners.owners( a2 )

実行結果です。

["136411120 : A", "136411140 : B"]
["136411130 : A"]
[]
[]

というか、デバッガを探せばこんな機能はありそうだな、と作ってからちょっと思った。