use*_*601 10 thread-safety raku
我正在尝试编写一个sub自动线程安全的特征。这就是我所拥有的:
#| A trait to ensure that a sub is not run on multiple threads simultaneously.
multi sub trait_mod:<is> (Sub \code, :$protected!) {
# If :!protected, do nothing.
if $protected {
# Create a new lock outside the multithreaded area
my $lock = Lock.new;
# Wrap the sub with a routine that hides callsame in a lock
code.wrap: sub (|) {
$lock.protect: {callsame}
}
}
}
#| Should print "Start X and finish X" if properly protected
sub needs-protection($x) is protected {
print "Start $x and ";
sleep 1;
say "finish $x";
}
# Test it out.
# If not protected, completes in 1 second with malformed output
(1..4).hyper(:1batch, :4degree) {
needs-protection $_
}
Run Code Online (Sandbox Code Playgroud)
然而,AFAICT,似乎callsame没有做任何事情(它返回Nil但就是这样)。我的猜测是它以某种方式试图为 调用不同的候选者.protect,但我没有看到一种方法来确保callsame链接到包装子,而不是其他一些方法。
我能够通过这样做来让它工作
multi sub trait_mod:<is> (Sub \code, :$protected!) {
if $protected {
my $lock = Lock.new;
code.wrap: sub (|c) {
if CALLERS::<$*PROTECTED> {
$*PROTECTED = False;
return callsame;
}
$lock.protect: {
my $*PROTECTED = True;
code.CALL-ME(|c);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但这感觉很笨拙,而且我可能遗漏了一些东西,当事情不安全时,它可以让True价值$*PROTECTED滑出。有没有办法callsame在protect-ed 块内直接进行while ?
Jon*_*ton 13
延迟例程,例如callsame寻找最近的动态范围分派以恢复。{callsame}传递给该方法的块protect将被该方法调用protect,并且动态范围内最近的分派将是方法分派到protect。因此,它将尝试遵循protect的基类中的方法Lock。没有,所以Nil结果。
为了解决这个问题,我们需要在正确的动态范围内获取被包装的目标,并使其在词法上可用。这可以使用nextcallee:
#| A trait to ensure that a sub is not run on multiple threads simultaneously.
multi sub trait_mod:<is> (Sub \code, :$protected!) {
# If :!protected, do nothing.
if $protected {
# Create a new lock outside the multithreaded area
my $lock = Lock.new;
# Wrap the sub with a routine that hides callsame in a lock
code.wrap: sub (|c) {
my &target = nextcallee;
$lock.protect: { target(|c) }
}
}
}
#| Should print "Start X and finish X" if properly protected
sub needs-protection($x) is protected {
print "Start $x and ";
sleep 1;
say "finish $x";
}
# Test it out.
# If not protected, completes in 1 second with malformed output
for (1..4).hyper(:1batch, :4degree) {
needs-protection $_
}
Run Code Online (Sandbox Code Playgroud)
这给出了我期望您期望的输出。
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |