
with_mutex(++Handle, +Goal)

   Equivalent to once(Goal) but with mutual exclusion

Arguments
   Handle              A handle for an object supporting mutual exclusion
   Goal                Callable term

Type
   Engines and Threads

Description

   This built-in can be used in multithreaded or parallel programs to
   implement mutual exclusion between concurrently running engines.
   Goals that are protected via with_mutex/2 on the same Mutex object
   can only be executed by one engine at a time.

   Note that in a side effect free program there is no need ever to worry
   about mutual exclusion.  Also, individual calls to built-ins performing
   side-effects (stream I/O operations, operations on nonlogical storage, etc)
   do not need extra protection, because they internally lock the object
   they operate on.  The purpose of with_mutex/2 is therefore to make a
   sequence of multiple side-effects atomic, when this is necessary to
   maintain consistency of shared data structures.

   The following object handles can be used as Mutex:

    stream handle
    shelf handle
    store handle
    bag handle
    record handle

   To obtain a handle from an object's alias name, use name_to_handle/3.
   There is currently no special-purpose 'mutex' handle: a dummy 'bag'
   object can be used for this purpose.  

   Mutexes are recursive, i.e. nested calls to with_mutex/2 within a
   thread are allowed.  Mutexes are automatically unlocked when the control
   flow leaves the with_mutex/2 predicate, whether via success, failure,
   throw/1 or exit/1.

   The standard precautions for working with mutexes apply: they should be
   held as briefly as possible to avoid unnecessary blocking of other threads.
   Also, nesting of (explicit or implicit) mutexes can lead to deadlocks.



Modes and Determinism
   with_mutex(++, +) is semidet

Modules
   This predicate is sensitive to its module context (tool predicate, see @/2).

Fail Conditions
   Fails if Goal fails

Exceptions
     4 --- Goal is not instantiated.
     5 --- Goal is not an atom or a compound term.
     5 --- Handle is not an object handle.
   141 --- Handle refers to an object that does not support this operation

Examples
   

    % make sure a list is printed in one chunk
    % use the stream's own mutex for exclusion
    atomic_write_list(Stream, List) :-
        with_mutex(Stream, write_list(Stream, List)).

    write_list(Stream, []) :- nl(Stream).
    write_list(Stream, [X|Xs]) :- writeln(Stream, X), write_list(Stream, Xs).


See Also
   once / 1, condition_signal / 2, condition_wait / 2, name_to_handle / 3, is_handle / 2
