%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%-----------------------------------------------------------------------------%
% 
% Test that io.update_globals/3 does not cause a deadlock in .par grades
% if the update closure throws an exception.  The initial version of
% io.update_globals/3 did *not* do this.
%
%-----------------------------------------------------------------------------%

:- module io_globals_deadlock.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is cc_multi.

:- implementation.

:- import_module exception.
:- import_module list.
:- import_module string.
:- import_module unit.
:- import_module univ.

main(!IO) :-
    io.set_globals(univ(3), !IO),
    try_io(update_pred_1, Result, !IO),
    (
        Result = succeeded(unit),
        io.write_string("update_pred_1 succeeded.\n", !IO)
    ;
        Result = exception(_),
        io.write_string("update_pred_1 threw exception.\n", !IO)
    ),
    % 
    % The following call to io.get_globals/3 will block if io.update_globals/3
    % fails to reset the lock after throwing an exception.
    %
    io.get_globals(Globals, !IO),
    det_univ_to_type(Globals, FinalValue),
    io.format("Final value of Globals = %d\n", [i(FinalValue)], !IO).

:- pred update_pred_1(unit::out, io::di, io::uo) is det.
    
update_pred_1(unit, !IO) :-
    io.update_globals(update_1, !IO).

:- pred update_1(univ::in, univ::out) is det.

update_1(!Univ) :-
    ( univ_to_type(!.Univ, N) ->
        ( N = 3 ->
            throw("N = 3")
        ;
            !:Univ = univ(561)
        )
    ;
        throw("cannot convert univ to integer")
    ).
