use strict;
use warnings;
use threads;
use threads::shared;
use Thread::Semaphore;
use Test::More;
use Config;
use UUID 'uuid4';

plan skip_all => 'perl not threaded'
    unless $Config{useithreads};

ok 1, 'loaded';

my $sync = 0;
my $seen = {};
my $mutex = Thread::Semaphore->new(0); # locked
share($sync);
share($seen);
share($mutex);

my ($t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19);
my ($t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29);
my ($t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39);

$t10 = threads->create(\&doit); $t11 = threads->create(\&doit);
$t12 = threads->create(\&doit); $t13 = threads->create(\&doit);
$t14 = threads->create(\&doit); $t15 = threads->create(\&doit);
$t16 = threads->create(\&doit); $t17 = threads->create(\&doit);
$t18 = threads->create(\&doit); $t19 = threads->create(\&doit);
$t20 = threads->create(\&doit); $t21 = threads->create(\&doit);
$t22 = threads->create(\&doit); $t23 = threads->create(\&doit);
$t24 = threads->create(\&doit); $t25 = threads->create(\&doit);
$t26 = threads->create(\&doit); $t27 = threads->create(\&doit);
$t28 = threads->create(\&doit); $t29 = threads->create(\&doit);
$t30 = threads->create(\&doit); $t31 = threads->create(\&doit);
$t32 = threads->create(\&doit); $t33 = threads->create(\&doit);
$t34 = threads->create(\&doit); $t35 = threads->create(\&doit);
$t36 = threads->create(\&doit); $t37 = threads->create(\&doit);
$t38 = threads->create(\&doit); $t39 = threads->create(\&doit);

until ($sync == 30) {
    select undef, undef, undef, 0.1;
    note "so far: $sync";
}

$mutex->up(30);  # thundering herd!

$t10->join; $t11->join; $t12->join; $t13->join; $t14->join; $t15->join;
$t16->join; $t17->join; $t18->join; $t19->join; $t20->join; $t21->join;
$t22->join; $t23->join; $t24->join; $t25->join; $t26->join; $t27->join;
$t28->join; $t29->join; $t30->join; $t31->join; $t32->join; $t33->join;
$t34->join; $t35->join; $t36->join; $t37->join; $t38->join; $t39->join;

sub doit {
    ++$sync;
    $mutex->down;
    my $uu = uuid4();
    $mutex->up;
    note $uu;
    ++$seen->{$uu};
}

is scalar(keys %$seen), 30, 'no dupes';
if ((scalar keys %$seen) != 0) {
    note "$_  $seen->{$_}"
        for sort keys %$seen;
}

done_testing;
