weakref.rb

Ruby勉強会in松江午後の部に参加.
みんな気の赴くままに,Rubyの何かをするという形式で非常に有意義だった.
 

weakref.rb

今回はRubyの標準ライブラリであるweakrefについて調べてみた.
弱い参照を作るライブラリで,C++で言う所のweak_ptrの様な動きをする.
 

サンプルコード

require 'weakref'
require 'pp'

foo = "123"
bar = WeakRef.new(foo)
bar << "45"
pp bar #=> "12345"
pp foo #=> "12345"
foo = nil # kill only ref

GC.start
pp bar # should raise exception (recycled)

こんな動きをするんだって.

実装はどうなっているのか

どうやってRubyで実現しているかと言うと,weakrefのクラス変数でIDを管理していた.
IDのクラスはFixnum.
いわゆるオブジェクトへの参照ではないのでGCでは無視される.

# weakref.rb
  def initialize(orig)
    #ID取得
    @__id = orig.object_id

    ...

    #クラス変数に保持,管理
    @@id_map[@__id].push self.object_id
    @@id_rev_map[self.object_id] = @__id
    ...
  end

initializeで返却する参照は実体のdelegatorである.
 
weakrefから実体を取得するときは

# weakref.rb
  def __getobj__
    ...
      ObjectSpace._id2ref(@__id)
    ...
  end

という形で実体を取ってくる.IDを参照に変換するみたい.
 

使用例

GoogleCodeSearchで検索するも使用例見つからず.
Wikipediaによると.

弱い参照が便利なひとつの例として、アプリケーション内で参照されている変数を追跡するケースがある。
この追跡リストは、対象オブジェクトに対して弱い参照で参照しなければならない。
そうしなければ、一度リストに加えられたオブジェクトはリストによって参照されるため、
プログラムが停止するまで半永久的に解放されることはない。

という事らしい.
おー,なるほど.あるオブジェクトの監視とかに使える訳かー.