Legend:
Library
Module
Module type
Parameter
Class
Class type
A Mutable structure akin to a Ringo.CACHE_MAP but with Lwt-aware functions. E.g., consider the following use of a Ringo.CACHE_MAP:
let c = Ringo_map.create 1024 in
let resolve k =
match Ringo_map.find_opt k with
| Some v -> Lwt.return v
| None ->
do_resolve k >>= fun v ->
Ringo_map.replace c k v;
Lwt.return v
In this example, there is a race condition: if do_resolve takes time to complete, another call to resolve may be made concurrently to the first one.
The function find_or_replace in Ringo_lwt.CACHE_MAP works around this issue.
The type of keys on which values in the cache are indexed.
type'a t
The type of Lwt-friendly caches holding bindings from key to 'a.
Instead of adding values directly to this cache, you can add promises (using replace) or, more interestingly, atomically (a) querying for an already bound promises or (b) generating a new one if needed. This helps avoid race conditions.
A promise is removed from the cache if:
The cache overflows (in which case, the removal of the promise depends on the policies of the cache, see Ringo.CACHE_MAP for details).
The promise is still held by the cache when
the cache is cleared (in which case the promise is canceled).
it is replaced by another one (in which case it is canceled).
it is explicitly removed (in which case it is canceled).
it is rejected.
If a promise is not held by the cache, then it cannot be removed from the cache and it will not be canceled by the cache.
replace c k p binds the key k to p in the cache c.
Note that when a promise is rejected, it is automatically removed from the cache.
Note that, for the purpose of determining if an inserted binding is supernumerary, and thus if it pushes another binding out of the cache, an unresolved binding counts fully.
fold f c init folds the function f and value init over the bindings of c. More specifically, it takes the bindings that are in c at the moment of the call (inserting a binding whilst the fold promise is pending has no effect on the fold promise) and traverses them sequentially: it waits for one step of the folding to resolve before starting the next one. Promises that are rejected are not visible by this fold operation: they are simply ignored.
E.g., you can run fold (fun _ _ () -> Lwt.return_unit) () to wait for all currently-held bindings to resolve.
Note that for some caches, this function may fold over a subset of the bindings of c. Specifically, on caches with a Weak overflow policy, only the strongly-held elements are folded over.
val fold_promises : (key->'aLwt.t->'b->'b)->'at->'b->'b
fold_promises f c init folds the function f and value init over the promises of bindings of c. More specifically, it takes the bindings that are in c at the moment of the call (inserting a binding whilst the fold promise is pending has no effect on the fold promise) and traverses them all immediately. The function that folds over the bindings is given the promises (rather than the values these promises resolve to).
E.g., You can count the number of resolved/pending like so: fold_promises
(fun _ p (sleeping, not_sleeping) ->
match Lwt.state p with
| Sleep -> (sleeping + 1, not_sleeping)
| Return _ -> (sleeping, not_sleeping + 1)
| Fail _ -> assert false (* these are removed from the cache *)
)
c
(0, 0)
Note that for some caches, this function may fold over a subset of the bindings of c. Specifically, on caches with a Weak overflow policy, only the strongly-held elements are folded over.
find_opt c k is None if k is not bound in c. Otherwise it is Some p where p is bound to k in c.
Note that the in some caches, this may have a side effect on the k-to-v binding. Specifically, in some caches, it might make it less likely to be removed when supernumerary bindings are inserted.
find_or_replace c k f behaves likes find_opt c k if k is bound in c, and it behaves like replace c k f otherwise. Either way, it returns the promise that resolves to the value associated to k whichever behavior find_or_replace resembled.
In the degenerate case where the cache is of size 0 (via a presized, empty cache), then f k is returned.