6

我在 OCaml。

我正在寻找模拟通信节点以查看消息在不同通信方案等下传播的速度。

节点可以 1. 发送和 2. 接收固定消息。我想显而易见的事情是将每个节点作为一个单独的线程。

显然,您可以使用 Event 模块和通道让线程相互传递消息,但我找不到任何示例。有人可以指出我正确的方向还是给我一个简单的相关示例?

非常感谢。

4

3 回答 3

7

如果您要尝试模拟,那么您将需要对节点进行更多的控制,而不是简单地使用线程所允许的——或者至少,没有大的痛苦。

我对该主题的主观方法是创建一个简单的单线程虚拟机,以保持对模拟的完全控制。在 OCaml 中最简单的方法是使用类似 monad 的结构(例如在 Lwt 中所做的):

(* 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 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

您可以创建更适合您需要的原语,例如在您的频道中添加“传输所需时间”属性。

下一步是定义模拟引擎。

(* 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 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 ]        
于 2012-02-13T18:08:40.547 回答
7

是的,您可以使用 OCaml 的Event模块。您可以在O'Reilly在线图书中找到其使用示例。

于 2012-02-12T09:58:18.400 回答
5

听起来您正在考虑 John Reppy 的Concurrent MLOCaml here似乎有类似的东西。

@Thomas 给出的答案也很有价值,但是如果您想使用这种并发编程风格,我建议您阅读 John Reppy 的博士论文,该论文非常易读,并且非常清楚地处理了 CML 背后的动机及其一些实质性示例利用。如果您对语义不感兴趣,则跳过该部分仍然可以阅读文档。

于 2012-02-12T01:00:23.713 回答