[m-dev.] for review: stream I/O

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Oct 3 13:06:00 AEDT 2000


On 03-Oct-2000, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > > 	- one to use when you don't care about the order of side
> > > 	  effects, even though they may influence the result
> > 
> > :- pred io__join(io__state::di, io__state::di, io__state::uo) is cc_multi.
> > 
> > Okay, this needs a bit of work...
> 
> Well, `spawn' in extras/concurrency/spawn.m provides one way of doing this.
> And if you just want

(Sorry, that was incomplete.  Here's what I meant to say:)

If you want a way of doing this without introducing multiple threads,
i.e. you just want to give the compiler permission to reorder the
operations without actually forcing it to create a new thread,
then we could provide something like this:

	:- pred io__split(pred(T, io__state, io__state, io__state, io__state),
			T, io__state, io__state).
	:- mode io__split(pred(out, di, uo, di, uo) is cc_multi,
			out, di, uo) is cc_multi.
	:- mode io__split(pred(out, di, uo, di, uo) is det,
			out, di, uo) is cc_multi.
		%
		% Operationally, io__split(Pred, Result, ...) just calls
		% Pred(Result, ...), passing it two pairs of io__states.
		% The side effects of the operations on each pair
		% occur in the order that those operations are called.
		% So if the strict sequential operational semantics is
		% requested, the order is completely specified, but in
		% general the order will be unspecified.
		% io__split does not create a new thread.
		%
		% Declaratively, io__split(Pred, Result, IO0, IO) is true
		% iff Pred(Result, IOA0, IOA, IOB0, IOB) is true, where
		% IOA0 and IOB0 are identical to IO0 except that they
		% each reflect the fact that the io__state has been split
		% (and hence operations on IOB0 can affect the results of
		% operations on IOA0 and vice versa),
		% and where IO is formed from IO0 by interleaving in any order
		% the two sequences of I/O actions that were applied to get
		% (1) from IOA0 to IOA and (2) from IOB0 to IOB.
		%

	:- implementation.

	:- pred io__fork_states(io__state::di, io__state::uo, io__state::uo) is det.
	:- pred io__join_states(io__state::di, io__state::di, io__state::uo) is cc_multi.

	:- pragma c_code(io__fork_states(_IO0::di, _IOA0::uo, _IOB0::uo),
		[thread_safe, will_not_call_mercury], "").
	:- pragma c_code(io__join_states(_IOA::uo, _IOB::uo, _IO::di),
		[thread_safe, will_not_call_mercury], "").

	io__split(Pred, Result, IO0, IO) :-
		io__fork_states(IO0, IOA0, IOB0),
		Pred(Result, IOA0, IOA, IOB0, IOB),
		io__join_states(IOA, IOB, IO).

Note that it's not safe to export io__fork_states and io__join_states,
since that would lead to semantic problems if io__fork_states is
called without a corresponding call to io__join_states, just like the
problem with stream__init/stream__destroy.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list