Can you upload a working example? That will really help with debugging.
The main thing that stands out to me right now is that having a global mutable variable will invariably lead to bugs. State should be created by and passed around between functions that need it, not stored at the module level.
So what I usually do when I write servers that utilize shared state, I make the global state is a module type and the modules using it would be functors.
module type STATE = sig
val global_list: int list ref
end
module Does_Whatever (S: STATE) = struct
...
end
let _ =
let state = module struct
let global_list = [] ref
end in
let D = Does_Whatever(state) in
D.{whatever_fns}
or
module State = struct
let global_list = [] ref
end
module D = Does_Whatever(State)
let _ =
D.whatever_fn [args]
If you’re using lwt/async.
module type SafeState = sig
type t
val mu: Lwt_mutex.t
val set: t -> t Lwt.t
val get: unit -> t Lwt.t
end
module type MutList = sig
type elt
val global_list : elt list ref
end
module GlobalList (M: MutList) : SafeState with type t = M.elt list = struct
let mu = Lwt_mutex.create ()
let set t =
let f () =
M.global_list := t;
Lwt.return t
in
Lwt_mutex.with_lock mu f
let get () =
!M.global_list |> Lwt.return
end
module Does_whatever(S: SafeState with type t = int list ) = struct
...
end