IPC-MMA

 view release on metacpan or  search on metacpan

t/09_lock.t  view on Meta::CPAN

    # a short while after process 3 (which has no lock at all) sees 19,
    #  sets 20 and requests a read lock (1 will have gotten its write
    #  lock by then)
    while (($myvar = $var) < 19) {usleep(DELTA_T)}
    if ($myvar == 19) {
        usleep(DELTA_T<<2);  # make sure #1 has requested its lock and is waiting
        $var = 20;
        if (!mm_lock($mm, MM_LOCK_RD)) {err 98}
        # when 3 gets its read lock, 1 is still waiting for its write lock,
        #   though there's the theoretical possibility that 1 has gotten
        #   its write lock and then released it
        while (($myvar = $var) < 22) {usleep(DELTA_T)}
        if ($myvar == 22) {
            $var = 23;
            if (!mm_unlock($mm)) {err 93}
        } elsif ($myvar == 24) {
            $var = 25;
            if (!mm_unlock($mm)) {err 93}
    }   }

} else {
    # when process 0 sees 20, it releases its read lock and
    #  advances to 21
    # then it continues to wait until a timeout, or it sees one of
    #  the terminating values
    $var = 18;
    $timer = 0;
    while (($myvar = $var) < 25 && $timer < TIMEOUT) {
        if ($myvar == 20) {
            if (mm_unlock($mm)) {$var = 21}
            else {
                $var = 90;
                usleep(DELTA_T<<4);  # let other activity settle
                $var = $myvar = 90;
                last;
        }   }
        # the while and if comparisons above take a significant number of uS
        #  so if TIMEOUT is to approximate real time, this delay has to be mS
        $timer += DELTA_T;
        usleep(DELTA_T);
    }
    # if timeout, test for other processes still around
    my $st='';
    if ($timer >= TIMEOUT
     && $myvar < 90) {
        for (my $i=1; $i<=3; $i++) {
            if (kill 0, $pid[$i]) {
                $st .= $st ? ", $i" : $i;
    }   }   }

    # create final result message
    my $mes = $myvar==97 ? "id 1 couldn't upgrade read to write lock"
            : $myvar==98 ? "id 3 couldn't get read lock"
            : $myvar>=90 ? "id ".($myvar-90)." couldn't unlock"
            : $myvar< 25 ? "state got stuck at $myvar"
            : "id 1 write lock "
            . ($myvar == 25 ? "was granted before a later id 3 read lock"
                            : "had to wait for a later id 3 read lock");

    # report the test result (2 results are OK)
    ok ($myvar == 25 || $myvar == 26, "$mes: " . ($st ? "process $st still alive" 
                                                      : "timer=$timer of ".TIMEOUT));

    kill 9, $pid[1], $pid[2], $pid[3];
    mm_destroy ($mm);
}
# success on test 11 means that a process can upgrade a read lock
#   to a write lock without first releasing the read lock
#   but online words say this upgrade is subject to an interloper
#   (which is indicated by a 'had to wait for a later' message)



( run in 0.776 second using v1.01-cache-2.11-cpan-ceb78f64989 )