■2006-02-05
* [Perl][メモ] threads関連:blessのサポート
threads::sharedはPerlの標準モジュールですが、CPANに最新の0.95があがっていてblessがサポートされたとあります。threadsのドキュメントには共有リファレンスをblessしても他のスレッドにはblessされたことが伝わらないとなっています。ところで実際に試してみると、Perl 5.8.0(threads::shared 0.90)では確かに全く対応していませんが、5.8.1以降は共有化されたハッシュリファレンスとスカラーリファレンスに関してはblessが伝搬されていました。ただしスカラーリファレンスはダメ。5.8.1以降のshared.xsファイルのソースをみるとblessが定義されていて、threads::sharedをuseするときにEXPORTされていたんですね。最新のthreads::shared 0.95でスカラーリファレンスもblessが伝搬されました。
use threads; use threads::shared; my $obj : shared; $obj = &share([]); threads->new(\&bless_test, $obj)->join; print ref($obj) , "\n"; $obj = &share({}); threads->new(\&bless_test, $obj)->join; print ref($obj), "\n"; $obj = &share(\1); threads->new(\&bless_test, $obj)->join; print ref($obj), "\n"; sub bless_test { my $obj_in_thr : shared = shift; bless $obj_in_thr, 'Foo'; }
それからPerl5.8.8でのithread関連:
・no warnings 'threads'が効くようになった
・$t->join()でスレッドインタプリタが解放されるようになり、メモリリークが修正された
これらに基づきメモを修正しました。
■2006-02-08
* [Per][メモ] XSモジュールのSTDERRをキャプチャする
変数内部を覗くに便利なDevel::Peek。問答無用でSTDERRに出力されます(perl内部のルーチン経由)。このSTDERRに出力されたデータを別ハンドルにリダイレクトしようとして知ったのですが、open my $fh, '>', \$var; *STDERR = $fh
みたいな方法ではXSモジュールのSTDOUTやSTDERRをリダイレクトできないんですね(PerlIOを経由しないからかしら?)(→追記:PerlIO経由のみなら大丈夫であることをコメント欄で教えていただきました)。例えばIO::Captureを使って
use IO::Capture::Stderr; my $capture = IO::Capture::Stderr->new(); $capture->start(); Dump("a"); # STDERRに出力される…… print STDERR "foo!"; $capture->stop(); print "stderr : ", $capture->read;
とやっても、foo!しか取得できません。それでpipeとforkを使って子プロセスにDevel::Peek::Dumpを実行させ、パイプ経由で親プロセスが出力を回収するモジュールを書いたのですが、CPANにはIO::CaptureOutputというモジュールがありました。このモジュールは一時ファイルを利用してサブプロセスやXSモジュールのSTDOUT, STDERRを変数にキャプチャします。
このモジュールを(そのままでは不都合があるので)少し弄くってつくったDevel::Peek::Capture。Devel::Peekと同じDumpがインポートされます。
use Devel::Peek::Capture; my $foo = {}; my $output = Dump($foo); print $output;
おまけで、ある変数が threads::shared
で共有化されているかどうかを判定する is_shared
がついてます。
■2006-02-16
* [今月のAcme] 閑話休題:threadsとencoding
えーと、先月に続き忙しくて日誌をつける気力がありません。もちろんAcme関連を書く気力もありません。ですので、ちょっと趣向を変えてthreadsとencodingについて書きます。ご存知のとおりencodingプラグマ(というかbinmode filehandle, layer
)とthreadsを併用するとPerlがクラッシュします。
use encoding 'euc-jp', STDOUT => 'shiftjis'; use threads; threads->new(\&subref)->join; # クラッシュ!
だいたいthreadsが使えるぐらいならutf8でソースを書いてuse utf8;
すればよいだけのことじゃないか、というのは言わない約束で。で、何とかthreadsとencodingを併用するお手軽な方法はないかと考えました。 ……
use acmencoding 'euc-jp', STDOUT => 'shiftjis'; use threads; threads->new(\&subref)->join; # クラッシュしない!
ご覧のように新たなプラグマ、acmencodingを使用すると、threadsと併用しても平気です。今ならおまけ機能として
use acmencoding ':binmode'; use threads; binmode(STDIN, ":raw :encoding(euc-jp)"); binmode(STDOUT, ":raw :encoding(shiftjis)"); threads->new(\&subref)->join; # クラッシュしない!
こんなこともできます。acmencoding.tar.gz。 あまり真面目に動作を期待しないでください。
_ H.Inaba [PerlIO経由だけであれば、一時ファイルがなくともできますね。 use Devel::Peek; my $std..]
_ まかまか [あ、ほんとだ。 簡単なデバッグ用ならこっちの方で良いですね。]