Previous: version_hash_table, Up: Top   [Contents]


126 version_store

%--------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%--------------------------------------------------%
% Copyright (C) 2004-2006, 2011 The University of Melbourne.
% Copyright (C) 2013-2016, 2018, 2022, 2024 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%--------------------------------------------------%
%
% File: version_store.m.
% Author: Ralph Becket <rafe@cs.mu.oz.au>
% Stability: low.
%
% See the header comments in version_array.m for an explanation of version
% types.
%
% A version_store is similar to, albeit slightly slower than, an ordinary
% store, but does not depend upon uniqueness.
%
% Note that, unlike ordinary stores, liveness of data is via the version store
% rather than the mutvars. This means that dead data (i.e. data whose mutvar
% is out of scope) in a version_store may not be garbage collected.
%
%--------------------------------------------------%
%--------------------------------------------------%

:- module version_store.
:- interface.

%--------------------------------------------------%

:- type version_store(S).

:- type mutvar(T, S).

    % Construct a new version store. This is distinguished from other
    % version stores by its existentially quantified type. This means
    % the compiler can automatically detect any attempt to use a mutvar
    % with the wrong version store.
    %
:- some [S] func init = version_store(S).

    % new_mutvar(X, Mutvar, VS0, VS) adds a new mutvar with value reference X
    % to the version store.
    %
:- pred new_mutvar(T::in, mutvar(T, S)::out,
    version_store(S)::in, version_store(S)::out) is det.

    % new_cyclic_mutvar(F, Mutvar, VS0, VS) adds a new mutvar with value
    % reference F(Mutvar) to the version store. This can be used to
    % construct cyclic terms.
    %
:- pred new_cyclic_mutvar((func(mutvar(T, S)) = T)::in, mutvar(T, S)::out,
    version_store(S)::in, version_store(S)::out) is det.

    % copy_mutvar(Mutvar, NewMutvar, VS0, VS) constructs NewMutvar
    % with the same value reference as Mutvar.
    %
:- pred copy_mutvar(mutvar(T, S)::in, mutvar(T, S)::out,
    version_store(S)::in, version_store(S)::out) is det.

    % lookup(VS, MutVar) = Element:
    % VS ^ elem(Mutvar) = Element:
    %
    % Return the Element referenced by Mutvar in the version store VS.
    %
:- func lookup(version_store(S), mutvar(T, S)) = T.
:- func elem(mutvar(T, S), version_store(S)) = T.

    % get_mutvar(Mutvar, Element, VS, VS):
    %
    % Return the Element referenced by Mutvar in the version store VS,
    % and also return the unchanged version store. This version of lookup
    % may be useful in code using state variables.
    %
:- pred get_mutvar(mutvar(T, S)::in, T::out,
    version_store(S)::in, version_store(S)::out) is det.

    % set(VS0, Mutvar, X) = VS:
    % set_mutvar(Mutvar, X, VS0, VS):
    % VS0 ^ elem(Mutvar) := X = VS:
    %
    % Update the version store VS0 so that Mutvar now refers to value X,
    % returning the new version store as VS.
    %
:- func set(version_store(S), mutvar(T, S), T) = version_store(S).
:- pred set_mutvar(mutvar(T, S)::in, T::in,
    version_store(S)::in, version_store(S)::out) is det.
:- func 'elem :='(mutvar(T, S), version_store(S), T) = version_store(S).

    % unsafe_rewind(VS) produces a version of VS for which all accesses
    % are O(1). Invoking this predicate renders undefined VS and all later
    % versions undefined that were derived by performing individual updates.
    % Only use this when you are absolutely certain there are no live
    % references to VS or later versions of VS.
    %
    % A predicate version is also provided.
    %
:- func unsafe_rewind(version_store(T)) = version_store(T).
:- pred unsafe_rewind(version_store(T)::in, version_store(T)::out) is det.

%--------------------------------------------------%
%--------------------------------------------------%


Previous: version_hash_table, Up: Top   [Contents]