[m-users.] spawn in Rosettacode

Mark Brown mark at mercurylang.org
Sat Sep 6 20:40:27 AEST 2014


On Sun, Aug 31, 2014 at 2:39 PM, Robert Smart
<robert.kenneth.smart at gmail.com> wrote:
> Thanks Mark. I've put a link a link to your email in my blog post on the
> subject
> (http://wombatlang.blogspot.com.au/2014/08/lazyness-backtracking-and-explicit-io.html).
> Mistakes in my post will be quickly fixed. I look forward to understanding
> it all better one day!

Regarding your question about joining threads, the sub-modules of
thread.m provide various kinds of synchronization which can achieve
this effect. There is no explicit join in the current release.

Here's a very simple example using a semaphore:

    main(IO0, IO) :-
        semaphore.init(S, IO0, IO1),
        spawn(signal(S), IO1, IO2),
        wait(S, IO2, IO).

(This requires a new mode for thread.spawn, with a det argument. That
mode would be generally useful. Can it be added to the standard
library?)

>From the declarative semantics, we can deduce that the sequence of
transactions will be one of:

    [semaphore.init(S), signal(S), wait(S)]
    [semaphore.init(S), wait(S), signal(S)]

The declarative semantics doesn't tell us anything about which
solution we get, but the operational semantics can constrain the
choice. We know that, operationally, wait/3 will block if the
semaphore counter is zero, but in the second sequence this does not
happen. Therefore the second sequence can be ruled out and the first
sequence must be the one that occurs.

Below is an implementation of the synchronous concurrency task
(http://rosettacode.org/wiki/Synchronous_concurrency). Perhaps Julien
could also review this and add it to Rosetta code?

Cheers,
Mark.


:- module synchronous_concurrency.
:- interface.

:- import_module io.

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

:- implementation.

:- import_module int.
:- import_module list.
:- import_module string.
:- import_module thread.
:- import_module thread.channel.
:- import_module thread.mvar.

:- type line_or_stop
    --->    line(string)
    ;       stop.

main(!IO) :-
    io.open_input("input.txt", Res, !IO),
    (
        Res = ok(Input),
        channel.init(Channel, !IO),
        mvar.init(MVar, !IO),
        thread.spawn(writer(Channel, MVar, 0), !IO),
        reader(Input, Channel, MVar, !IO)
    ;
        Res = error(Err),
        io.format("Error opening file: %s\n", [s(io.error_message(Err))], !IO)
    ).

:- pred reader(io.input_stream::in, channel(line_or_stop)::in, mvar(int)::in,
    io::di, io::uo) is det.

reader(Input, Channel, MVar, !IO) :-
    io.read_line_as_string(Input, Res, !IO),
    (
        Res = ok(Line),
        channel.put(Channel, line(Line), !IO),
        reader(Input, Channel, MVar, !IO)
    ;
        Res = eof,
        channel.put(Channel, stop, !IO),
        mvar.take(MVar, Count, !IO),
        io.format("%d lines printed.\n", [i(Count)], !IO)
    ;
        Res = error(Err),
        channel.put(Channel, stop, !IO),
        io.format("Error reading file: %s\n", [s(io.error_message(Err))], !IO)
    ).

:- pred writer(channel(line_or_stop)::in, mvar(int)::in, int::in,
    io::di, io::uo) is cc_multi.

writer(Channel, MVar, Count, !IO) :-
    channel.take(Channel, LineOrStop, !IO),
    (
        LineOrStop = line(Line),
        io.write_string(Line, !IO),
        writer(Channel, MVar, Count + 1, !IO)
    ;
        LineOrStop = stop,
        mvar.put(MVar, Count, !IO)
    ).



More information about the users mailing list