区分一个子调用与另一个子调用

pil*_*row 4 perl multithreading

在下面的片段中,如何区分sub的第二个调用实例和foo第一个?

while ($whatever) {
  foo(); foo();     # foo() and foo() have the same caller package, file, and line
}
Run Code Online (Sandbox Code Playgroud)

caller()返回文件,的超级东西就可以了.我不想使用源过滤器.

背景,或者,这不是一个XY问题吗?

我有一个便利模块,Local :: Thread :: Once,它以OO-ish方式公开像pthread_once/ 一样的功能std::call_once,也作为子程序属性.这些都很容易,因为在任何一种情况下都有一个自然而明确的"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;
}
Run Code Online (Sandbox Code Playgroud)

这并不是它的工作原理 - 实际的更有效 - 但重点是,调用是从调用者的文件和行中键入的.这是有效的,除了它无法区分同一行上的两个调用.

while ($whatever) {
  once { foo(); }
  once { bar(); }                    # OK, foo() and bar() each called only once
  once { baz(); }; once { buz(); };  # :(  buz() not called, not even once
}
Run Code Online (Sandbox Code Playgroud)

请注意,地址$user_routine不能用作附加判别式,因为subs从一个ithread复制到另一个.

我可以将这个问题视为一个非常人为的用例的文档限制,但我更愿意以某种方式修复它.

tob*_*ink 6

Devel :: Callsite正是为此目的编写的.