Skip to content

Commit ece1b7f

Browse files
committed
Add a future data type for concurrent and parallel programming
library/library.m: library/thread.future.m: library/thread.m: Add new future standard library module. NEWS: Announce the new addition. library/thread.semaphore.m: Add an impure interface to thread.semaphore.m. Semaphores are used to implement our other concurrency primitives and an impure interface can often be useful to implement things such as futures, which don't require IO state threading. The impure interface predicate names are prefixed with "impure_". library/thread.semaphore.m: NEWS: Deprecate the impure init/1 function. library/thread.mvar.m: Conform to changes in semaphore.m. benchmarks/progs/mandelbrot/mandelbrot.m: Add future example to mandelbrot benchmark.
1 parent 33be5c8 commit ece1b7f

File tree

7 files changed

+444
-75
lines changed

7 files changed

+444
-75
lines changed

NEWS

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,18 @@ Changes to the Mercury standard library:
2424
highly efficient set implementation for fat sets. This module is a
2525
contribution from Yes Logic Pty. Ltd.
2626

27-
* We have added a module that implements barriers for concurrent
28-
programming. This module is a contribution from Mission Critical IT.
27+
+ We have added two new modules for concurrent programming: thread.barrier
28+
and thread.future. The barrier module provides a barrier type which can
29+
be used to control progress in concurrent code. The future module
30+
provides future and future_io data types which can be used to compute
31+
values in parallel using other threads. These modules were contributed by
32+
Mission Critical IT.
2933

3034
* We have added thread.spawn_native/4 to dedicate an OS thread to a Mercury
3135
thread. thread.spawn/4 was added as well.
3236

37+
+ We have deprecated the impure init/1 function in thread.semaphore.
38+
3339
* In C grades, the math module now provides the fused multiply-add operation
3440
on platforms that support it.
3541

benchmarks/progs/mandelbrot/mandelbrot.m

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
:- import_module require.
2222
:- import_module string.
2323
:- import_module thread.
24+
:- import_module thread.future.
2425
:- import_module thread.mvar.
2526

2627
main(!IO) :-
@@ -115,6 +116,7 @@
115116
---> parallel_conj
116117
; parallel_spawn
117118
; parallel_spawn_native
119+
; parallel_future
118120
; sequential.
119121

120122
:- pred process_options(option_table(option)::in, maybe_error(options)::out)
@@ -143,13 +145,16 @@
143145
;
144146
ParallelStr = "spawn_native",
145147
Parallel0 = parallel_spawn_native
148+
;
149+
ParallelStr = "future",
150+
Parallel0 = parallel_future
146151
)
147152
->
148153
MaybeParallel = ok(Parallel0)
149154
;
150155
MaybeParallel = error(
151-
"Parallel must be one of ""no"", ""conj"", ""spawn"" or " ++
152-
"""spawn_native""")
156+
"Parallel must be one of ""no"", ""conj"", ""spawn"", " ++
157+
"""spawn_native"" or ""future""")
153158
),
154159

155160
getopt.lookup_maybe_int_option(Table, dim_x, MaybeX),
@@ -198,9 +203,11 @@
198203
"\t\tThe dimensions of the image, specify neither or both\n", !IO),
199204
write_string("\t-p <how> --parallel <how>\n", !IO),
200205
write_string(
201-
"\t\t<how> is one of ""no"", ""conj"", ""spawn"" or\n", !IO),
206+
"\t\t<how> is one of ""no"", ""conj"", ""spawn"",\n", !IO),
207+
write_string(
208+
"\t\t""spawn_native"" or ""future"". These may be grade", !IO),
202209
write_string(
203-
"\t\t""spawn_native"". These may be grade dependent.\n", !IO),
210+
"\t\tdependent.\n", !IO),
204211
write_string("\t-d --dependent-conjunctions\n", !IO),
205212
write_string(
206213
"\t\tUse an accumulator to represent the rows rendered so far\n", !IO).
@@ -241,14 +248,20 @@
241248
:- pred draw_rows_dep(parallel::in, list(float)::in, list(float)::in,
242249
cord(colour)::out) is det.
243250

244-
draw_rows_dep(sequential, Xs, Ys, Rows) :-
245-
map_foldl(draw_row(Xs), append_row, Ys, empty, Rows).
246-
draw_rows_dep(parallel_conj, Xs, Ys, Rows) :-
247-
map_foldl_par_conj(draw_row(Xs), append_row, Ys, empty, Rows).
248-
draw_rows_dep(parallel_spawn, Xs, Ys, Rows) :-
249-
map_foldl_par_spawn(draw_row(Xs), append_row, Ys, empty, Rows).
250-
draw_rows_dep(parallel_spawn_native, Xs, Ys, Rows) :-
251-
map_foldl_par_spawn_native(draw_row(Xs), append_row, Ys, empty, Rows).
251+
draw_rows_dep(Parallel, Xs, Ys, Rows) :-
252+
(
253+
Parallel = sequential,
254+
map_foldl(draw_row(Xs), append_row, Ys, empty, Rows)
255+
;
256+
Parallel = parallel_conj,
257+
map_foldl_par_conj(draw_row(Xs), append_row, Ys, empty, Rows)
258+
;
259+
( Parallel = parallel_spawn
260+
; Parallel = parallel_spawn_native
261+
; Parallel = parallel_future
262+
),
263+
sorry($file, $pred, string(Parallel))
264+
).
252265

253266
:- pred draw_rows_indep(parallel::in, list(float)::in, list(float)::in,
254267
cord(colour)::out) is det.
@@ -270,6 +283,9 @@
270283
promise_equivalent_solutions [RowList] (
271284
my_map_par_spawn_native(draw_row(Xs), Ys, RowList)
272285
)
286+
;
287+
Parallel = parallel_future,
288+
my_map_par_future(draw_row(Xs), Ys, RowList)
273289
),
274290
foldl(append_row, RowList, empty, Rows).
275291

@@ -375,22 +391,6 @@
375391
map_foldl_par_conj(M, F, Xs, !Acc)
376392
).
377393

378-
:- pred map_foldl_par_spawn(pred(X, Y), pred(Y, A, A), list(X), A, A).
379-
:- mode map_foldl_par_spawn(pred(in, out) is det, pred(in, in, out) is det,
380-
in, in, out) is erroneous.
381-
382-
map_foldl_par_spawn(_, _, _, !Acc) :-
383-
% XXX: Do the parallel conjunction transformation by hand.
384-
sorry($file, $pred, "Unimplemented").
385-
386-
:- pred map_foldl_par_spawn_native(pred(X, Y), pred(Y, A, A), list(X), A, A).
387-
:- mode map_foldl_par_spawn_native(pred(in, out) is det,
388-
pred(in, in, out) is det, in, in, out) is erroneous.
389-
390-
map_foldl_par_spawn_native(_, _, _, !Acc) :-
391-
% XXX: Do the parallel conjunction transformation by hand.
392-
sorry($file, $pred, "Unimplemented").
393-
394394
:- pred my_map(pred(X, Y), list(X), list(Y)).
395395
:- mode my_map(pred(in, out) is det, in, out) is det.
396396

@@ -407,6 +407,16 @@
407407
M(X, Y) &
408408
my_map_par_conj(M, Xs, Ys).
409409

410+
:- pred my_map_par_future(pred(X, Y), list(X), list(Y)).
411+
:- mode my_map_par_future(pred(in, out) is det, in, out) is det.
412+
413+
my_map_par_future(_, [], []).
414+
my_map_par_future(M, [X | Xs], Ys) :-
415+
FutY = future((func) = Y0 :- M(X, Y0)),
416+
my_map_par_future(M, Xs, Ys0),
417+
Y = wait(FutY),
418+
Ys = [Y | Ys0].
419+
410420
:- pred my_map_par_spawn(pred(X, Y), list(X), list(Y)).
411421
:- mode my_map_par_spawn(pred(in, out) is det, in, out) is cc_multi.
412422

library/library.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@
301301
mercury_std_library_module("thread").
302302
mercury_std_library_module("thread.barrier").
303303
mercury_std_library_module("thread.channel").
304+
mercury_std_library_module("thread.future").
304305
mercury_std_library_module("thread.mvar").
305306
mercury_std_library_module("thread.semaphore").
306307
mercury_std_library_module("tree234").

0 commit comments

Comments
 (0)