« 4章.参照渡しと値渡し (その6) | メイン | 4章.参照渡しと値渡し (その8) »

4章.参照渡しと値渡し (その7)

 今回のエントリは、「4.3 未知のオブジェクトとDRbUnknown」です。前回のエントリでは4章全体のまとめも合わせて一つのエントリにすると言いましたが、(あわせると長くなりそうなので)やっぱり分けることにしました。

 はい、ではDRbUnknownって何なんでしょう、何のためにあるのでしょう。本を読みます。

DRbUnknownとは知らないクラスをMarshal.loadしてしまったときの例外を捉え、ロードできなかったオブジェクトの代わりにロードされるオブジェクトです。 DRbUnknownはロードに失敗した原因を、二つ保持しています。一つはロードに失敗したバッファ、もう一つは定義が不明なクラス名/モジュール名です。

それぞれ次のメソッドで問い合わせることができます。

DRbUnknown#buf
Marshal.loadに失敗した直列化されたオブジェクトのバッファ。
DRbUnknown#name
例外のメッセージから調べた、未知のクラス/モジュール名。
DRbUnknown#reload
もう一度Marshal.loadしてみる。

4.3 未知のオブジェクトとDRbUnknown

メモメモ。続きも読んでみます。

dRubyのライブラリは知らないクラスを受けとってしまっても、そのバッファを包んだ DRbUnknownオブジェクトを自動的に生成します。 DRbUnknownに対して元のオブジェクトのつもりでメソッドを呼ぶことはできませんが、DRbUnknownを回送することはできます。

4.3 未知のオブジェクトとDRbUnknown

 ほうほうです。Marshalを使うと、マーシャルデータからオブジェクトを復元するとき(Marshal.loadするとき)に、そのオブジェクトの型を知っていないと復元できないみたいです。dRubyではオブジェクトを渡すときにMarshalの仕組みを利用していますので、この挙動から影響を受けるんですね。

 DRbUnknownの中身をちょっとだけ見てみます。小さなクラスなので見やすいです。まずは_dumpメソッドから。

def _dump(lv) # :nodoc:
  @buf
end

_dumpはMarshalでのdump時に呼ばれるメソッドであることは前回のエントリで勉強しました。なので、DRbUnknownが別プロセスに渡されるときには、DRbUnknownが包んでいる元々のマーシャルデータが渡されます。で、受け取ったプロセスで復元できたらそれでよし、復元できなければそこでもDRbUnknownになります。ってことですね。

 ちなみに、@nameを設定している部分はここです。

def initialize(err, buf)
  case err.to_s
  when /uninitialized constant (\S+)/
@name = $1
  when /undefined class\/module (\S+)/
@name = $1
  else
@name = nil
  end
  @buf = buf
end

 例外の文字列から名前を取っているみたいです。$1ってのは、正規表現にマッチした最初の文字列が入ってる組み込み変数です。@nameがnilになることもあるのか。elseに入るのはどういうときなのかなあ、名前すらわからないエラーのときですよねきっと。多分marchal.cの


static VALUE
r_object0(arg, proc, ivp, extmod)
struct load_arg *arg;
VALUE proc;
int *ivp;
VALUE extmod;
{
・・・

のメソッドあたりで投げられている例外の大半が該当するのだと思います。実際にDRbUnknownが捕捉している例外の文字列はvariable.cから出るやつのようです。中身はややこしそうなので追わないことにしました。このくらいにして本を読み進めます。

DRbUnknownの機構によって、クラス定義を知らないオブジェクトを(メソッド呼び出しはできないが)保持しておくことが可能になります。

プロセス間でオブジェクトを交換するためのQueueを考えてみましょう。中継するQueueのサービスがpushされる可能性のある全てのクラス定義を事前に知らなくてはならないのは、難しいことがあります。 DRbUnknownはこういった局面で特に有用な機能です。

4.3 未知のオブジェクトとDRbUnknown

 本に書かれていることはよくわかります。プロセス間通信を行う上では、サービス側が全てのオブジェクトの型を知っておくことは非現実的であったり面倒であったりすることが多いです。なので、dRubyでは、マーシャルデータからオブジェクトを復元することが出来なくても、それを保持できる仕組みを提供しています。それがDRbUnknownです。

 ちょっとかなり端折り気味ですが、以下にまとめを書いてDRbUnknownは終わりにします。一度は本の内容にそって実験してみて下さいね。

DRbUnknownのまとめ


  • DRbUnknownオブジェクトはMarshal.loadが失敗したときに生成される

  • DRbUnknownオブジェクトは、オブジェクトに復元できなかったマーシャルデータの情報を保持する

  • DRbUnknownオブジェクトの状態では、(中身のオブジェクトの)メソッドを呼べない

  • DRbUnknownオブジェクトをdumpすると、包み込んでいるマーシャルデータがそのまま返される

  •  つまりdRubyでのプロセス間通信時には、気にせずそのままホイホイ渡せばいい
  • Marshal.loadが成功したら、DRbUnknownオブジェクトの中身のオブジェクトが取れる


次回こそ、4章を終わりにします。

トラックバック

このエントリーのトラックバックURL:
http://www.grandnature.net/bin/mt-tb.cgi/71

コメントを投稿

About

2007年11月07日 09:47に投稿されたエントリーのページです。

ひとつ前の投稿は「4章.参照渡しと値渡し (その6)」です。

次の投稿は「4章.参照渡しと値渡し (その8)」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。