In the following snippet, how can I distinguish the second instance of my sub foo call from the first?
while ($whatever) { foo(); foo();
Something like super- caller() , which returned the file, row and column, would do the trick. I would prefer not to use source filters.
Background, or, is this not a XY problem?
I have a convenience module, Local :: Thread :: Once, which provides functions like pthread_once / std::call_once in the OO-ish way, and also as an attribute of a subroutine. This is easy enough, because in any case there is a natural and unambiguous "once_control" or "once_flag".
However, there is also a procedural interface - once { ... } - which is currently serialized based on the $filename and $line returned by caller . Something like that:
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; }
It's not exactly how it works — real — more efficient, but again, it's that the call is called from the file and the line of the caller. This works, except that it cannot distinguish between two calls on the same line.
while ($whatever) { once { foo(); } once { bar(); } # OK, foo() and bar() each called only once once { baz(); }; once { buz(); }; # :( buz() not called, not even once }
Please note that the address $user_routine cannot be used as an additional discriminant, since subs are copied from one, etc. to another.
I can live with this problem as a documented limitation for a very far-fetched use case, but I would rather fix it somehow.