[m-rev.] For review: ensure proper initialisation of pretty_printer

Ralph Becket rafe at csse.unimelb.edu.au
Thu Apr 22 15:46:50 AEST 2010


If this could be reviewed quickly, that would be great.  I'm using
this patch to track down a problem in the G12 IC solver.

Estimated hours taken: 2
Branches: main

There is a race condition between the initialisation of modules
and mutables, mainly because there is no guaranteed order of
initialisation.  This is a problem for pretty_printer.m since
we would like other modules to be able to register formatters
for types they define via an ':- initialise' directive.

This patch fixes the problem by using C instead of a mutable
for the default formatter map variable.

Index: library/pretty_printer.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/pretty_printer.m,v
retrieving revision 1.9
diff -u -r1.9 pretty_printer.m
--- library/pretty_printer.m	18 May 2009 05:55:13 -0000	1.9
+++ library/pretty_printer.m	22 Apr 2010 05:39:14 -0000
@@ -884,7 +884,7 @@
 %-----------------------------------------------------------------------------%
 % Convenience predicates.
 
-:- mutable(io_formatter_map, formatter_map, initial_formatter_map, ground,
+:- mutable(io_formatter_map, formatter_map, new_formatter_map, ground,
     [attach_to_io_state, untrailed, thread_local]).
 
 :- mutable(io_pp_params, pp_params, pp_params(78, 100, triangular(100)),
@@ -892,16 +892,76 @@
 
 %-----------------------------------------------------------------------------%
 
+    % Because there is no guaranteed order of module initialisation, we need
+    % to ensure that we do the right thing if other modules try to update the
+    % default formatter_map before this module has been initialised.
+    %
+    % All of this machinery is needed to avoid a race condition between
+    % initialise directives and initialisation of mutables.
+    %
+:- pragma foreign_decl("C",
+"
+    static MR_Bool pretty_printer_is_initialised = MR_FALSE;
+    static MR_Word pretty_printer_default_formatter_map = NULL;
+").
+
+%-----------------------------------------------------------------------------%
+
+:- pred pretty_printer_is_initialised(bool::out, io::di, io::uo)
+        is det.
+
+:- pragma foreign_proc("C",
+        pretty_printer_is_initialised(Okay::out, _IO0::di, _IO::uo),
+        [promise_pure, will_not_call_mercury, thread_safe],
+"
+    Okay = pretty_printer_is_initialised;
+").
+
+%-----------------------------------------------------------------------------%
+
+    % This predicate must not be called unless pretty_printer_is_initialised ==
+    % MR_TRUE, which occurs when set_default_formatter_map has been called at
+    % least once.
+    %
+:- pred unsafe_get_default_formatter_map(formatter_map::out, io::di, io::uo)
+        is det.
+
+:- pragma foreign_proc("C",
+        unsafe_get_default_formatter_map(FMap::out, _IO0::di, _IO::uo),
+        [promise_pure, will_not_call_mercury, thread_safe],
+"
+    FMap = pretty_printer_default_formatter_map;
+").
+
+%-----------------------------------------------------------------------------%
+
 get_default_formatter_map(FMap, !IO) :-
-    get_io_formatter_map(FMap, !IO).
+    pretty_printer_is_initialised(Okay, !IO),
+    (
+        Okay = no,
+        FMap = initial_formatter_map,
+        set_default_formatter_map(FMap, !IO)
+    ;
+        Okay = yes,
+        unsafe_get_default_formatter_map(FMap, !IO)
+    ).
 
-set_default_formatter_map(FMap, !IO) :-
-    set_io_formatter_map(FMap, !IO).
+%-----------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+        set_default_formatter_map(FMap::in, _IO0::di, _IO::uo),
+        [promise_pure, will_not_call_mercury],
+"
+    pretty_printer_default_formatter_map = FMap;
+    pretty_printer_is_initialised = MR_TRUE;
+").
+
+%-----------------------------------------------------------------------------%
 
 set_default_formatter(ModuleName, TypeName, Arity, Formatter, !IO) :-
-    get_io_formatter_map(FMap0, !IO),
+    get_default_formatter_map(FMap0, !IO),
     FMap = set_formatter(ModuleName, TypeName, Arity, Formatter, FMap0),
-    set_io_formatter_map(FMap, !IO).
+    set_default_formatter_map(FMap, !IO).
 
 %-----------------------------------------------------------------------------%
 
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list