次のフラグメントでは、サブルーチンの 2 番目の呼び出しインスタンスを最初の呼び出しインスタンスとどのように区別できますfoo
か?
while ($whatever) {
foo(); foo(); # foo() and foo() have the same caller package, file, and line
}
file、line、columncaller()
を返すsuper- のようなものがうまくいきます。ソース フィルターは使用しない方がよいでしょう。
背景、または、これは少し XY 問題ではありませんか?
私は便利なモジュール、Local::Thread::Once を持っています。これはpthread_once
/のような機能std::call_once
を OO 風の方法で、またサブルーチン属性として公開します。どちらの場合も、自然で明確な「once_control」または「once_flag」があるため、これらは簡単です。
ただし、現在、およびによって返されるonce { ... }
に基づいてシリアル化する手続き型インターフェイス — — が追加されています。このようなもの:$filename
$line
caller
sub once(&) {
my $user_routine = shift;
my (undef, $file, $line) = caller;
my $once_control = get_a_shared_flag_just_for_this_invocation($file, $line);
lock($once_control);
if (! $once_control) { $once_control++; $user_routine->(); }
return;
}
それは正確にはどのように機能するわけではありません — 実際のものはより効率的です — しかし、要点は、呼び出し元のファイルと行に基づいて呼び出しが行われるということです。これは機能しますが、同じ行での 2 つの呼び出しを区別できないことを除きます。
while ($whatever) {
once { foo(); }
once { bar(); } # OK, foo() and bar() each called only once
once { baz(); }; once { buz(); }; # :( buz() not called, not even once
}
$user_routine
サブルーチンはある ithread から別の ithread にコピーされるため、 のアドレスを追加の判別式として使用できないことに注意してください。
この問題は、非常に不自然なユースケースの文書化された制限として受け入れることができますが、どうにかして修正したいと考えています。