Skip to content

Commit

Permalink
Add module Ref for persistent references
Browse files Browse the repository at this point in the history
  • Loading branch information
balat committed Jun 11, 2024
1 parent cf907fa commit 45cebda
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/dbm/ocsipersist.ml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ module Functorial = struct
end

module Polymorphic = Ocsipersist_lib.Polymorphic (Functorial)
module Ref = Ocsipersist_lib.Ref (Store)

type 'value table = 'value Polymorphic.table

Expand Down Expand Up @@ -322,6 +323,7 @@ type 'value table = 'value Polymorphic.table
(fun () -> Unix.close socket; return ()))
(fun e -> Unix.close socket; Lwt.fail e))))
*)

let init () =
if !Ocsipersist_settings.delay_loading
then
Expand Down
6 changes: 6 additions & 0 deletions src/ocsipersist.mli
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ module Polymorphic : Ocsipersist_lib.Sigs.POLYMORPHIC
type 'value table = 'value Polymorphic.table
(** Table representation as generated by the function {!Polymorphic.open_table} *)

module Ref : Ocsipersist_lib.Sigs.REF
(** Simple interface for persistent references.
Relies on {!Stdlib.Marshal} for (de)serialisation, which entails
the same limitations as for the {!Polymorphic} frontend. If this is an
issue you can rely on {!Functorial} frontend instead (see {!TABLE.Variable}). *)

module Store : Ocsipersist_lib.Sigs.STORE
(** The variable store allows for the persistent storage of individual
variables. Relies on {!Stdlib.Marshal} for (de)serialisation, which entails
Expand Down
52 changes: 52 additions & 0 deletions src/ocsipersist_lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,29 @@ module Sigs = struct
*)
end

module type REF = sig
(** Persistent references for OCaml *)

type 'a t
(** The type of (persistent or not) references *)

val ref : ?persistent:string -> 'a -> 'a t
(** [ref ?persistent default] creates a reference.
If optional parameter [?persistent] is absent,
+ the reference will not be persistent (implemented using OCaml references).
+ Otherwise, the value of [persistent] will be used as key for the
+ value in the persistent reference table.
If the reference already exists, the current value is kept.
+ Be careful to change this name every time you change the type of the
+ value. *)

val get : 'a t -> 'a Lwt.t
(** Get the value of a reference *)

val set : 'a t -> 'a -> unit Lwt.t
(** Set the value of a reference *)
end

module type STORE = sig
type 'a t
(** Type of persistent data *)
Expand Down Expand Up @@ -263,3 +286,32 @@ struct

let set {name} = T.add name
end

module Ref (Store : STORE) = struct
let store = lazy (Store.open_store "__ocsipersist_ref_store__")

type 'a t = Ref of 'a ref | Per of 'a Store.t Lwt.t

let ref ?persistent v =
match persistent with
| None -> Ref (ref v)
| Some name ->
Per
(let%lwt store = Lazy.force store in
Store.make_persistent ~store ~name ~default:v)

let get = function
| Ref r -> Lwt.return !r
| Per r ->
let%lwt r = r in
Store.get r

let set r v =
match r with
| Ref r ->
r := v;
Lwt.return_unit
| Per r ->
let%lwt r = r in
Store.set r v
end
2 changes: 2 additions & 0 deletions src/pgsql/ocsipersist.ml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ module Store = struct
exec db query [Key p.name; Value v] >> Lwt.return ()
end

module Ref = Ocsipersist_lib.Ref (Store)

type store = Store.store
type 'a variable = 'a Store.t

Expand Down
1 change: 1 addition & 0 deletions src/sqlite/ocsipersist.ml
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ module Functorial = struct
end

module Polymorphic = Ocsipersist_lib.Polymorphic (Functorial)
module Ref = Ocsipersist_lib.Ref (Store)

type 'value table = 'value Polymorphic.table

Expand Down

0 comments on commit 45cebda

Please sign in to comment.