[ Engines and Threads | Reference Manual | Alphabetic Index ]

with_mutex(++Handle, +Goal)

Equivalent to once(Goal) but with mutual exclusion
Handle
A handle for an object supporting mutual exclusion
Goal
Callable term

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:

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

Modules

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

Fail Conditions

Fails if Goal fails

Exceptions

(4) instantiation fault
Goal is not instantiated.
(5) type error
Goal is not an atom or a compound term.
(5) type error
Handle is not an object handle.
(141) unimplemented functionality
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