package store

  1. Overview
  2. Docs
Snapshottable data structures

Install

dune-project
 Dependency

Authors

Maintainers

Sources

store-v0.2.tar.bz2
sha512=42d6c7a850a7ac113c5470d6ebe9b5a160a9aa57d009b7eda17a14cda5a54a1dcecd146281322da70579bab08ede70ebe23aa5c48cc3ad3c2c90098424fafbb7

doc/store/Store/Absorbing/index.html

Module Store.AbsorbingSource

An absorbing structure in a store.

Absorbing structures are used-defined structures that behave very much like store references, except that the logic to "capture" the current value of the reference and to "restore" past or future values is user-defined.

The push-only queue that logs some events that we used to document Free structures above can also be presented as an absorbing interface, which is more efficient: only the first push of a sequence of pushes requires Store book-keeping, until the next capture.

  module Log = struct
    type 'a s = 'a Stack.t
    type 'a t = 'a s Store.Absorbing.t
  
    type 'a op = {elems: 'a list}
    type anti = {len: int}
    type 'a descr = ('a s, 'a op, anti) Store.Absorbing.descr
  
    let capture s = {len = Stack.length s}
  
    let rollback s anti =
      let len = Stack.length s in
      for _ = anti.len to len - 1 do
        Stack.drop s
      done
  
    let undo s anti =
      let len = Stack.length s in
      let rec collect acc = function
        | 0 -> acc
        | n -> collect (Stack.pop s :: acc) (n - 1)
      in
      {elems = collect [] (len - anti.len)}
  
    let redo s op =
      let before_len = Stack.length s in
      List.iter (fun x -> Stack.push x s) op.elems;
      { len = before_len }
  
    let descr : 'a descr = {
      capture;
      rollback;
      undo;
      redo;
    }
  
    let create () =
      Store.Absorbing.make descr (Stack.create ())
        
    let log store (s : 'a t) (event : 'a) =
      let stack = Store.Absorbing.get s in
      Store.Absorbing.modify store s;
      Stack.push event stack
    
    let events (s : 'a t) : 'a list =
      let stack = Store.Absorbing.get s in
      Stack.fold (fun acc x -> x::acc) [] stack
  end
Sourcetype ('s, 'ops, 'anti) descr = {
  1. capture : 's -> 'anti;
    (*

    Capture the current state in a backtracking point.

    The state at the time of capture can be restored by calling rollback, provided that the current state of the data structure is a descendant of that state.

    In other words, the captured state can be restored using rollback, but only from a state reachable from the captured state using only user-facing operations.

    *)
  2. rollback : 's -> 'anti -> unit;
    (*

    Reset the state to what it was at the time of capture.

    *)
  3. undo : 's -> 'anti -> 'ops;
    (*

    Reset the state to what it was at the time of capture, and returns a set of user-facing operations that can be used to redo the modifications.

    *)
  4. redo : 's -> 'ops -> 'anti;
    (*

    Redo the modifications.

    *)
}

User-provided functions to operate on a custom structure.

Note: These functions are not allowed to operate on the store -- they must not read or modify stored references or structures -- as they may be called when the store is in an inconsistent intermediary state.

The type 's is the (mutable) type of the absorbing structure.

The type 'op is the type of sequences of operations on the absorbing structure.

The type 'anti is the type of antioperations, undoing operations on the absorbing structure. Each antioperation acts like a snapshot that can return to a previous state of the structure.

Sourcetype 's t
Sourceval make : ('s, 'ops, 'anti) descr -> 's -> 's t
Sourceval get : 's t -> 's
Sourceval modify : store -> 's t -> unit

This function must be called before modifying the state of an absorbing reference.