R u*_*c k 7 events ocaml channel message-passing
我在OCaml.
我希望模拟通信节点,以查看消息在不同通信方案下传播的速度等.
节点可以1.发送和2.接收固定消息.我想明显要做的是将每个节点作为一个单独的线程.
显然,您可以使用事件模块和通道获取线程以相互传递消息,但我找不到任何此示例.有人能指出我正确的方向还是只给我一个简单的相关例子?
非常感谢.
如果您要尝试模拟,那么您需要对节点进行更多控制,而不仅仅是使用线程允许 - 或者至少没有重大痛苦.
我对该主题的主观方法是创建一个简单的单线程虚拟机,以便完全控制模拟.在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
Run Code Online (Sandbox Code Playgroud)
您可以创建更适合您需求的原语,例如在频道中添加"传输所需的时间"属性.
下一步是定义模拟引擎.
(* 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
Run Code Online (Sandbox Code Playgroud)
同样,您可以调整引擎以跟踪正在执行哪个节点的节点,保持每个节点的优先级,以便模拟一个节点比其他节点更慢或更快,或者随机选择一个线程在每个步骤执行,以及等等.
最后一步是执行模拟.在这里,我将有两个线程来回发送随机数.
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 ]
Run Code Online (Sandbox Code Playgroud)
这听起来像是在考虑John Reppy的Concurrent ML.似乎是OCaml的类似的东西在这里.
@Thomas给出的答案也很有价值,但是如果你想使用这种并发编程的方式,我建议你阅读John Reppy的博士论文,这篇论文极具可读性,并对CML背后的动机以及它的一些实际例子进行了非常明确的处理.使用.如果您对语义不感兴趣,那么如果您跳过该部分,该文档仍然可读.
| 归档时间: |
|
| 查看次数: |
1942 次 |
| 最近记录: |