Обнаружение глобального разрушения в Perl - PullRequest
5 голосов
/ 04 февраля 2011

Я хотел бы определить, является ли мой объект DESTROY частью глобального уничтожения, и распечатать предупреждение (поскольку это, очевидно, было бы ошибкой и привело бы к потере данных). Очевидный способ сделать это выглядит так:

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";
    }
}'

Ответы [ 2 ]

10 голосов
/ 04 февраля 2011

Есть модуль Devel :: GlobalDestruction , который использует чуть-чуть XS, чтобы позволить вам напрямую получить флаг глобального уничтожения.

Обновление: с тех пор perl 5.14.0 есть глобальная переменная ${^GLOBAL_PHASE}, которая будет установлена ​​на "DESTRUCT" во время глобального уничтожения.Вы все равно должны использовать Devel :: GlobalDestruction, так как он работает с perls до 5.6.При установке на Perl с ${^GLOBAL_PHASE} он использует встроенную функцию и даже не требует компилятора C для сборки.

8 голосов
/ 05 февраля 2011

Для меня достаточно хорошего решения - установить флаг в блоке END.

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