[ 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:

- 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) 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