File: 03-semaphore.t

package info (click to toggle)
nqp 2022.12%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,436 kB
  • sloc: java: 28,030; perl: 3,394; ansic: 451; makefile: 200; javascript: 68; sh: 1
file content (81 lines) | stat: -rw-r--r-- 2,331 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
plan(12);

my class Semaphore is repr('Semaphore') { }

# 9 tests
# Single threaded case
{
    my $s := nqp::box_i(3, Semaphore);

    nqp::semacquire($s);
    ok(1, 'semacquire of permit 1 of 3 succeeds');
    nqp::semacquire($s);
    ok(1, 'semacquire of permit 2 of 3 succeeds also');
    ok( nqp::semtryacquire($s), 'semtryacquire of permit 3 of 3 succeeds');
    ok(!nqp::semtryacquire($s), 'semtryacquire underflow fails');

    nqp::semrelease($s);
    ok(1, 'semrelease of permit 3 of 3 succeeds');
    ok(nqp::semtryacquire($s),  'semtryacquire of permit 3 of 3 succeeds now');

    nqp::semrelease($s);
    nqp::semrelease($s);
    nqp::semrelease($s);
    ok(1, 'semrelease of all three permits succeed');

    nqp::semrelease($s);
    nqp::semacquire($s);
    nqp::semacquire($s);
    nqp::semacquire($s);
    ok( nqp::semtryacquire($s), 'Release overflow adds to available capacity');
    ok(!nqp::semtryacquire($s), 'Semaphore does not grant more than overflow level in additional capacity');
}

# 3 tests
# Multi-threaded case
{
    my $released := 0;
    my $s  := nqp::box_i(3, Semaphore);
    my $t1 := nqp::newthread({
        nqp::semacquire($s);
    }, 0);
    my $t2 := nqp::newthread({
        nqp::semacquire($s);
    }, 0);
    my $t3 := nqp::newthread({
        nqp::semacquire($s);
    }, 0);
    my $t4 := nqp::newthread({
        ok(!nqp::semtryacquire($s), 'Trying fourth acquire before release fails');
    }, 0);
    my $t5 := nqp::newthread({
        my $before := nqp::time();
        nqp::semacquire($s);
        my $after  := nqp::time();
        ok($after - $before > 1000000000, 'Fourth acquire blocks on empty semaphore');
        ok($released, 'Fourth acquire succeeds after release in other thread');
    }, 0);
    my $t6 := nqp::newthread({
        nqp::sleep(3.0);
        $released := 1;
        nqp::semrelease($s);
    }, 0);

    # First, exhaust semaphore capacity
    nqp::threadrun($t1);
    nqp::threadrun($t2);
    nqp::threadrun($t3);
    nqp::threadjoin($t1);
    nqp::threadjoin($t2);
    nqp::threadjoin($t3);

    # Try (and fail) to acquire another permit
    nqp::threadrun($t4);
    nqp::threadjoin($t4);

    # Block on acquire, release in separate thread, succeed
    nqp::threadrun($t5);
    nqp::threadrun($t6);
    nqp::threadjoin($t6);
    nqp::threadjoin($t5);
}