如果您要尝试模拟,那么您需要比仅使用线程更多地控制节点,否则将会非常困难。
对于这个话题,我的主观做法是创建一个简单的单线程虚拟机,以便完全控制模拟。在OCaml中最简单的方法是使用类似单子的结构(例如在Lwt中使用的方式):
type thread = < run : thread list ; block : bool >
let write r x next = object (self)
method block = !r <> None
method run = if self # block then [self]
else r := Some x ; [next ()]
end
let read r next = object (self)
method block = !r = None
method run = match r with
| None -> [self]
| Some x -> r := None ; [next x]
end
您可以创建适合自己需求的更好的基元,例如在通道中添加“传输所需时间”属性。
下一步是定义模拟引擎。
let simulate threads =
let q = Queue.create () in
let () = List.iter (fun t -> Queue.push t q) 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 # block then (
Queue.push thread q ;
loop (blocking + 1)
) else (
List.iter (fun t -> Queue.push t q) (thread # run) ;
loop 0
)
in
loop 0
再次强调,您可以调整引擎以跟踪执行哪个线程的节点,以保持每个节点的优先级,以模拟一个节点比其他节点慢得多或快得多,或在每个步骤中随机选择要执行的线程等等。
最后一步是执行模拟。在这里,我将有两个线程来回发送随机数。
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" a b ; thread "B -> A" b a ]