Files
mercury/tests/stm/conflict.m
Zoltan Somogyi fdd141bf77 Clean up the tests in the other test directories.
tests/invalid/*.{m,err_exp}:
tests/misc_tests/*.m:
tests/mmc_make/*.m:
tests/par_conj/*.m:
tests/purity/*.m:
tests/stm/*.m:
tests/string_format/*.m:
tests/structure_reuse/*.m:
tests/submodules/*.m:
tests/tabling/*.m:
tests/term/*.m:
tests/trailing/*.m:
tests/typeclasses/*.m:
tests/valid/*.m:
tests/warnings/*.{m,exp}:
    Make these tests use four-space indentation, and ensure that
    each module is imported on its own line. (I intend to use the latter
    to figure out which subdirectories' tests can be executed in parallel.)

    These changes usually move code to different lines. For the tests
    that check compiler error messages, expect the new line numbers.

browser/cterm.m:
browser/tree234_cc.m:
    Import only one module per line.

tests/hard_coded/boyer.m:
    Fix something I missed.
2015-02-16 12:32:18 +11:00

93 lines
2.7 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ff=unix ts=4 sw=4 et
%
% Contains a predicate that reads an STM var then holds the transaction open
% while it waits, and another predicate that opens a transaction, waits, and
% then writes to an STM var. Used to ensure that a transaction reads an STM var,
% then a parallel transaction writes to the same var and commits before the read
% transaction can commit.
%---------------------------------------------------------------------------%
:- module conflict.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is cc_multi.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module thread.
:- import_module stm_builtin.
:- import_module list.
:- import_module int.
:- import_module string.
%---------------------------------------------------------------------------%
main(!IO) :-
new_stm_var(0, TVar, !IO),
thread.spawn(read_and_wait(TVar, 2), !IO),
thread.spawn(wait_and_write(TVar, 1, 28), !IO).
%---------------------------------------------------------------------------%
:- pred read_and_wait(stm_var(int)::in, int::in, io::di, io::uo) is cc_multi.
:- pragma promise_pure(read_and_wait/4).
read_and_wait(TVar, Delay, IO0, IO) :-
atomic [outer(IO0, IO1), inner(STM0, STM)] (
trace [io(!IO)] (
print("entering read transaction\n", !IO)
),
read_stm_var(TVar, X, STM0, STM),
trace [io(!IO)] (
format("value read was: %d\n", [i(X)], !IO)
),
impure sleep(Delay)
),
format("read transaction committed: X=%d\n", [i(X)], IO1, IO).
:- pred wait_and_write(stm_var(int)::in, int::in, int::in, io::di, io::uo)
is cc_multi.
:- pragma promise_pure(wait_and_write/5).
wait_and_write(TVar, Delay, X, IO0, IO) :-
atomic [outer(IO0, IO1), inner(STM0, STM)] (
impure sleep(Delay),
trace [io(!IO)] (
print("entering write transaction\n", !IO)
),
write_stm_var(TVar, X, STM0, STM),
trace [io(!IO)] (
format("wrote value: %d\n", [i(X)], !IO)
)
),
print("write transaction committed\n", IO1, IO).
%---------------------------------------------------------------------------%
:- pragma foreign_decl("C",
"
#include <unistd.h>
").
:- impure pred sleep(int::in) is det.
:- pred sleep(int::in, io::di, io::uo) is det.
:- pragma promise_pure(sleep/3).
sleep(Seconds, !IO) :-
impure sleep(Seconds).
:- pragma foreign_proc("C",
sleep(Seconds::in),
[will_not_call_mercury, thread_safe],
"
sleep(Seconds);
").