2011-02-04 4 views
5

私のオブジェクトがグローバル破壊の一部としてDESTROYであるかどうかを検出したいと思います。警告が表示されます(これは明らかにエラーでデータ消失につながります)。それを行うには明白な方法があるように見えるでしょう:Perlでのグローバル破壊の検出

sub DESTROY { 
    my $self = shift; 
    # ⋮ 
    if (i_am_in_global_destruction()) { 
     warn "I survived until global destruction"; 
    } 
} 

が、私は世界の破壊を検出するための良い方法を見つけることができなかった(代わりに通常の参照カウントを0破壊を打ちます)。それは5.10.1および5.8.8で動作しても「良い方法」、私はこれがないわけで

は、おそらく二誰かがそれを奇妙な一見を与える破る:

sub DESTROY { 
    $in_gd = 0; 
    { 
     local $SIG{__WARN__} = sub { $_[0] =~ /during global destruction\.$/ and $in_gd = 1 }; 
     warn "look, a warning"; 
    } 
    if ($in_gd) { 
     warn "I survived until global destruction"; 
    } 
}' 
+0

オブジェクトが破棄されたときにオブジェクトの内容を保存するだけでなく、グローバルな破壊中であるかどうかを心配する必要はありませんか? – Ether

+0

@Ether:グローバル破壊の順序は定義されていないので、私は私のものを保存するために他のオブジェクトが必要です。 – derobert

+3

私は( 'Devel :: GlobalDestruction'ソースから)v5.13.7には' '$ {^ GLOBAL_PHASE}'(http://search.cpan.org/~jesse/perl-5.13.9)があります/pod/perl5137delta.pod#New_global_variable_${^GLOBAL_PHASE})この変数はこの目的に適しています。 – mob

答えて

10

モジュールがありますDevel::GlobalDestructionこれは、XSの小さなビットを使用して、グローバルな破壊フラグを直接得ることができます。

更新:グローバル破壊時に"DESTRUCT"に設定されるグローバル変数${^GLOBAL_PHASE}ありperl 5.14.0以来。あなたはPerlで5.6に戻って動作するので、一般的にはDevel :: GlobalDestructionを使うべきです。 ${^GLOBAL_PHASE}でperlにインストールするときは、組み込み機能を使用し、Cコンパイラをビルドする必要はありません。

+2

ありがとうございます!また、Debianは 'libdevel-globaldestruction-perl'としてパッケージ化されています。 – derobert

8

私には十分な解決策は、ENDブロックにフラグを設定することです。

package Whatever; 
our $_IN_GLOBAL_DESTRUCTION = 0; 
END { 
    $_IN_GLOBAL_DESTRUCTION = 1; 
} 
+0

他のパッケージのENDブロックが実行される前に実行される可能性があるため、必ずしも動作しません。 – Ether

+3

また、すべてのENDブロックが完了した後で、技術的にグローバルな破壊が発生します。最悪の場合、別のENDブロックで破壊されている間に何かが間違っている可能性があります。 – mob

関連する問題