2011-02-04 21 views
5

में वैश्विक विनाश का पता लगाना मैं जानना चाहता हूं कि मेरा उद्देश्य वैश्विक विनाश के हिस्से के रूप में DESTROY 'डी है, और एक चेतावनी मुद्रित करें (क्योंकि यह स्पष्ट रूप से एक त्रुटि होगी और डेटा हानि का कारण बन जाएगा)। ऐसा करने के लिए स्पष्ट तरीका होने लगते हैं:पर्ल

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

लेकिन मैं वैश्विक विनाश का पता लगाने के लिए एक अच्छा तरीका खोजने में असमर्थ किया गया है (सामान्य refcount के बजाय 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

@ ईथर: क्योंकि वैश्विक विनाश का आदेश अपरिभाषित है, और मुझे अपनी वस्तुओं को बचाने के लिए अन्य वस्तुओं की आवश्यकता है। – 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 है जो आपको वैश्विक विनाश ध्वज पर सीधे जाने के लिए एक्सएस के एक छोटे से बिट का उपयोग करता है।

अद्यतन:perl 5.14.0 के बाद से वहाँ एक वैश्विक चर ${^GLOBAL_PHASE} कि वैश्विक विनाश के दौरान "DESTRUCT" करने के लिए सेट हो जाएगा। आपको अभी भी डेवेल :: ग्लोबलडिस्ट्रक्शन का उपयोग करना चाहिए, क्योंकि यह प्रतिलिपि 5.6 के साथ काम करता है। ${^GLOBAL_PHASE} के साथ एक पर्ल पर स्थापित करते समय यह अंतर्निर्मित सुविधा का उपयोग करेगा और निर्माण करने के लिए सी संकलक की आवश्यकता भी नहीं होगी।

+2

धन्यवाद! और डेनी के लिए इसे 'libdevel-globaldestruction-perl' के रूप में भी पैक किया गया है, क्योंकि लेनी कम नहीं है। – derobert

8

एक समाधान जो मेरे लिए पर्याप्त है वह END ब्लॉक में ध्वज सेट करना है।

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

यह आवश्यक रूप से काम नहीं करेगा, क्योंकि अन्य पैकेज 'ईएनडी ब्लॉक उस से पहले निष्पादित हो सकते हैं। – Ether

+3

इसके अलावा, सभी ईएनडी ब्लॉक पूरा होने के बाद वैश्विक विनाश तकनीकी रूप से होता है - इसलिए यहां सबसे खराब मामला यह है कि यह किसी अन्य ईएनडी ब्लॉक में नष्ट होने पर गलत तरीके से कुछ ध्वजांकित कर सकता है। – mob