If you are going to try the simulation, you will need a lot more control over your nodes than just using threads will allow - or at least without serious pain.
My subjective approach to this topic would be to create a simple single-threaded virtual machine to provide complete control over the simulation. The easiest way to do this in OCaml is to use a monad-like structure (as is done in Lwt, for example):
(* A thread is a piece of code that can be executed to perform some side-effects and fork zero, one or more threads before returning. Some threads may block when waiting for an event to happen. *) type thread = < run : thread list ; block : bool > (* References can be used as communication channels out-of-the box (simply read and write values ot them). To implement a blocking communication pattern, use these two primitives: *) let write rx next = object (self) method block = !r <> None method run = if self
You can create the best primitives that suit your needs, for example, add the "time required for transmission" property to your channels.
The next step is to determine the modeling mechanism.
(* The simulation engine can be implemented as a simple queue. It starts with a pre-defined set of threads and returns when no threads are left, or when all threads are blocking. *) let simulate threads = let q = Queue.create () in let () = List.iter (fun t -> Queue.push tq) threads in let rec loop blocking = if Queue.is_empty q then `AllThreadsTerminated else if Queue.length q = blocking then `AllThreadsBlocked else let thread = Queue.pop q in if thread
Again, you can configure the engine to track that the node is executing this thread, to maintain priorities for the node, to simulate a single node that was significantly slower or faster than others, or arbitrarily choose a thread to execute at each step, etc.
The last step is the simulation. Here I will have two threads sending random numbers back and forth.
let rec thread name input output = write output (Random.int 1024) (fun () -> read input (fun value -> Printf.printf "%s : %d" name value ; print_newline () ; thread name input output )) let a = ref None and b = ref None let _ = simulate [ thread "A -> B" ab ; thread "B -> A" ba ]
Victor nicollet
source share