sub safe_set {
my $k = shift;
my $v :shared = shift;
lock $$h{ $k };
$h{$k} = \$v;
}
####
TIMESTEP 0:
Say, $h{$k} points to v1
Thread T0: Holding lock on v1
Thread T1: Waiting on Lock on v1
TIMESTEP 1:
T0 changes $h{$k} = \$v2, releases lock on $v1
TIMESTAMP 2: (Thread T2 makes an entrance)
Thread T2: Acquires Lock on v2, proceeds
Thread T1: Acquires Lock on v1, proceeds
####
#! perl -slw
use strict;
use threads;
use threads::shared;
our %h : shared;
# Setting up just a single row to increase chances
# a race condition
our $k = 'AAA';
our $val : shared = 0;
our $THREADS = 50;
our $iter = 50;
$h{$k} = \$val;
# Safe_set similar to BrowserUk
sub safe_set {
my $v :shared;
# Critical Section
{
lock ${$h{$k}};
$v = ${$h{$k}} + 1;
$h{$k} = \$v;
}
}
# Keep locking to increment $$h{$k}
sub test_safe_set {
for (my $i = 0; $i < $iter; ++$i) {
safe_set();
}
}
my @pool = map{
threads->create(\&test_safe_set)
} 1 .. $THREADS;
$_->join for @pool;
warn ${$h{$k}}, "failed\n" if ${$h{$k}} != $THREADS * $iter;