Module Stateful.Pool

type 'a t

A pool of previously generated values. Not thread-safe.

Rules can add to it and draw from it, so a rule can use values that another rule produced rather than a new drawn value.

Create one with create and populate it with add. To draw from the pool, use the following generators:

  • values_reusable: drawing from it returns a value in the pool without removing it.
  • values_consumed: drawing from it removes a value from the pool and returns it.

Example: a resource allocator. The alloc rule creates a new handle and deposits it in the pool. The free rule draws one of those handles back out and releases it. Without a pool, free would have no way to name a handle that a previous alloc actually created. It could only draw an arbitrary integer, most of which name no live resource.

type state =
  { mutable live : int list
  ; handles : int Stateful.Pool.t
  }

let alloc =
  Stateful.Rule.create
    ~name:"alloc"
    ~step:(fun tc state ->
      let h = fresh_handle () in
      Stateful.Pool.add state.handles tc h;
      state.live <- h :: state.live)
    ()
;;

let free =
  Stateful.Rule.create
    ~name:"free"
    ~step:(fun tc state ->
      (* draws a handle a prior [alloc] put in the pool *)
      let h = draw_silent tc (Stateful.Pool.values_consumed state.handles) in
      release h;
      state.live <- List.filter (fun x -> x <> h) state.live)
    ()
;;
val create : ?clone:('a -> 'a) -> test_case -> 'a t

Creates an empty pool. Pools are tied to a test case. Do not reuse one across test cases. Drawn mutable values are shared by default. Pass a copying function for independent mutable values. Consumed draws return the stored value directly. clone must not call back into the same pool.

val add : 'a t -> test_case -> 'a -> unit

add pool tc value records value in pool.

let n = draw tc (integers ~min_value:0 ~max_value:100 ()) in
Stateful.Pool.add pool tc n
val size : _ t -> int

Returns the number of values in the pool.

assume tc (Stateful.Pool.size pool > 0)
val values_reusable : 'a t -> ('a, Generators.unprintable) Generators.generator

Draws a value without removing it. A draw from an empty pool rejects the current rule.

let existing = draw_silent tc (Stateful.Pool.values_reusable pool)
val values_consumed : 'a t -> ('a, Generators.unprintable) Generators.generator

Draws and removes a value. A draw from an empty pool rejects the current rule.

let taken = draw_silent tc (Stateful.Pool.values_consumed pool)